SAMURAI TERAKOYA

[ React hooks ] useRefの使い方・サンプルコード (useStateとの違いも解説!)

React.js

Reactを活用したフロントエンド開発においてデータを保持する場合、「useState」や「useReducer」を用いる方法が頭に浮かんでくるかと思います。

しかし、方法としてはもう一つありまして、それが今回ご紹介する「useRef」になります。

本記事では、useStateやuseReducerと同じReact hooksの一つである「useRef」の使い方やuseStateとの違いについて解説させて頂ければと思います。

また、useRefと関連しているhooksについての簡単な紹介と実際に動きとしても理解していけるようにサンプルコードを提供しておりますので、参考にしてもらえたらと思います。

useRefとは

useRefは、useState・useReducerと同じくコンポーネント内でデータを保持するためのReact hooks(関数)になります。また、DOMへの参照も可能であるため、マウント時にDOMの関数を呼び出したりすることが出来ます。

保持しているデータが書き換えられた際に更新されたデータを保持するオブジェクトをrefオブジェクト(ref属性)といい、DOMへアクセスする際にも用います。

言葉だと理解しにくいため、以下の例をご覧ください。useRefと紐づいている要素にて設定されているデータをcurrentプロパティに保持しているため、currentプロパティへアクセスすると値を取得することが出来ます。

useRef_refオブジェクト_イメージ

useRefとuseState・useReducerの違い

以下のような違いがあります。

  1. 保持しているデータが更新されても再レンダリングされない (useState・useReducerは、更新時に再レンダリングされる)
  2. useRefは、データの保持はされるがStateとしては認識されない
  3. マウント時にDOMの参照が行われ、DOMの関数やプロパティへアクセスが出来る
保持しているデータが更新されるたびに、.current プロパティを更新されたDOMノードへ設定されます。ref属性を設定している書き換え可能なデータが.current プロパティへ設定されると考えてもらえればと思います。
useRefで保持しているデータは、Stateとしては認識されないため、状態を管理する際は、useStateもしくはuseReducerを使うようにしましょう。

useRefの使い方

ここでは具体的な使い方と動作を確認していきます。簡単なカウンター機能の作成に加えて、ref属性を設定した要素の現在のデータの取得をみましょう。

カウンター機能の作成

カウンター機能
  • Appコンポーネントの修正

    まずは、src/App.jsを開き、以下のように修正しましょう。

    const App = () => {
      return (
        <></>
     )
    }
    
    export default App

  • useRef関数をインポートする

    Appコンポーネントの上部に次のコードを記述してください。

    import {useRef} from "react"
    

  • useRefを定義, JSXを記述

    useRefの定義

    変数countには、counterの現在のデータ(0)を取得しています。

    const counter = useRef(0)
    let count = counter.current

    JSXを記述

    +ボタンをクリックした場合は、handleAddClick関数を呼び出し、-ボタンがクリックされるとhandleMinusClick関数を呼び出すようにします。

    return (
      <>
        <button onClick={handleAddClick}>+</button>
        <button onClick={handleMinusClick}>-</button>
      </>
    )

  • 加算・減算するための関数を定義

    +ボタンがクリックされた時は、変数countの値を+1し、-ボタンをクリックされたら-1するようにします。また、加算できるのは100までとし、count内のデータが100の場合は、0にします。

    減算の際にも0未満にはならないようにします。

    const handleAddClick = () => { 
      console.log(count !== 100 ? count++ :  0)
    }
    
    const handleMinusClick = () => {
      console.log(count !== 0 ? count-- :  0)
    }

  • 最終コード

    import {useRef} from "react"
    
    const App = () => {
    
      const counter = useRef(0)
      let count = counter.current
    
      const handleAddClick = () => { 
        console.log(count !== 100 ? count++ :  0)
      }
    
      const handleMinusClick = () => {
        console.log(count !== 0 ? count-- :  0)
      }
    
      return (
        <>
          <button onClick={handleAddClick}>+</button>
          <button onClick={handleMinusClick}>-</button>
        </>
     )
    }
    
    export default App

  • 動作確認

     

    加算

    useRef_count_加算

    減算

    初期値を0より大きい値にしたうえで、確かめてみましょう。

    useRef_count_減算

ref属性を設定

手順③までは、カウンター機能の部分と同じになります。

refの設定とデータの取得
  • useRefを定義, JSXを記述

    useRefの定義

    const input = useRef(null)

    JSXを記述

    useRefと紐づけるinput要素へref属性を設定しています。

    return (
      <>
        <input ref={input} />
        <button onClick={InputText}>クリック</button>
      </>
    )

  • ボタンがクリックされた際に呼ばれる関数を定義

    const InputText = () => {  
      console.log(input.current.value)
    }

  • 最終コード

    import {useRef} from "react"
    
    const App = () => {
    
      const input = useRef(null)
    
      const InputText = () => {  
        console.log(input.current.value)
      }
    
      return (
        <>
          <input ref={input} />
          <button onClick={InputText}>クリック</button>
        </>
      )
    }
    
    export default App

  • 動作確認

    useRef_ref属性_input要素

useImperativeHandleの活用

useStateやuseReducerとの違いの部分で、少し触れましたが、useRefは保持しているデータが更新されても再レンダリングされません。つまりは、更新されたことを知らせないということです。

保持しているデータが更新される際(コンポーネントに対し、refが渡された時)に、親コンポーネントのrefに代入(設定)されるデータを設定する際に使われるのが、useImperativeHandleです。こちらもhooksの一種でありますが、使用することで以下のことが出来ます。

  • 子コンポーネントが持つデータを参照
  • 子コンポーネント内で定義されている関数を親コンポーネントから呼び出したりすることが可能である

今回は、具体的な使い方は省きますが、useRefと一緒に覚えておくことをオススメします。

まとめ

  • useRefは、useState・useReducerと同じくコンポーネント内でデータを保持するためのReact hooksです。useState・useReducerとは違い、保持しているデータの更新時に再レンダリングが発生しません。
  • データの保持はされるがStateとしては認識されないため、状態の管理はuseStateかuseReducerを使うようにする
  • また、refオブジェクトをコンポーネントへ渡すと、要素のマウント時にDOMの関数などを呼び出すことが可能です。
  • useRefと関連しているhooksとしてuseImperativeHandleがある。

コメント

タイトルとURLをコピーしました