useRefの使い方を復習する

2021-01-04

概要

React hooksには便利な機能が多くありますが、その中でuseRefに焦点を当てて考えてみます。

用途

useRefには主に以下の役割があります。

  • DOMの参照
  • 値の保持

使用例

ここからは活用例をあげていきます。

フォームからテキストを表示させる例

import React from 'react'

export default function App() {
  const [text, setText] = React.useState<string>("")
  const inputEl = React.useRef<HTMLInputElement>(null)
  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault()

    if (inputEl.current) {
      setText(inputEl.current.value)
    }
  }

  return (
    <div className="App">
      <form onSubmit={handleSubmit}>
        <label htmlFor="name">name</label>
        <input id="name" type="text" ref={inputEl} />
        <input type="submit" value="送信" />
      </form>
      <p>Your text is {text}</p>
    </div>
  )
}

useRefでinputを参照し、送信時にローカルステートにセットしています。
利点は、参照しているDOMの値を常に保持しているので扱いが容易になる点です。

useRef使用の変数は再描画されない

useRefで定義した値は再描画されても保持されていきます。

import React from 'react'

const App: React.FC = () => {
  let count: number = 0
  const countRef = React.useRef<number>(0)
  const [state, update] = React.useState<string>('state')
  console.log(countRef.current)

  const handleClick = () => {
    count++
    countRef.current++
    update(`${state}-update`)
  }

  return (
    <>
        <ul>
          <li>count1: {count}</li>
          <li>count2: {countRef.current}</li>
          <li>state: {state}</li>
        </ul>
        <button onClick={() => handleClick()}>ボタン</button>
    </>
  )
}

export default App

普通の変数count、useRef使用の変数countRefを用意しました。
update関数で意図的に状態を変更しているため、ボタンを押すごとにコンポーネントが再描画されます。

普通の変数では、再描画で初期値になるため0のままです。
useRef使用変数だと、再描画されても値を保持するので望んだ挙動ができています。

親から子へref参照ができる

親コンポーネントから子コンポーネントへ参照も可能です。

import React, { useRef, useEffect } from 'react'

const Child = React.forwardRef((props, ref) => {
  return (
    <div ref={ref}>DOM {props.text}</div>
  )
})

const Parent = () => {
  const el = useRef(null)

  useEffect(() => {
    console.log(el.current)
  }, [])

  return (
    <Child ref={el} text="Ref" />
  )
}

export default Parent

複数のDOM参照

一挙に複数のDOMの管理はどうしたらよいでしょうか。
以下のようにすれば複数参照が可能です。

import React, { useRef, useEffect } from 'react'

const data = ['dog', 'cat', 'rabbit']

const Component = () => {
  const refs = useRef([])
  data.forEach((_, i) => {
    refs.current[i] = React.createRef()
  })

  useEffect(() => {
    const animals = refs.current.map(item => item.current.innerText).join(',')
    console.log(animals)
  }, [])

  return (
    <div>
      {
        data.map((animal, i) => {
          return (
            <div key={animal} ref={refs.current[i]} >{animal}</div>
          )
        })
      }
    </div>
  )
}

export default Component

refsの中にデータ分のrefオブジェクトを作成する方法です。

結論

useRefを使っていくとDOMの参照がしやすく、また応用も効いてきます。
最後に紹介した複数参照も活用すると便利です。

運営について

Natural Tearoomはシステム開発会社フロントエンドエンジニアがんちゃんが運営するメディアです。
フロントエンド技術を中心に発信しています。

· プライバシーポリシー

SNS

© 2021 天然珈琲店