React hooksとは
React 16.8 で追加された新機能です。
クラスを書かなくても、 stateなどのReactの機能を、関数コンポーネントでシンプルに扱えるようになりました。
- React hooksを基礎から理解する (useState編)
- React hooksを基礎から理解する (useEffect編)
- React hooksを基礎から理解する (useContext編)
- React hooksを基礎から理解する (useReducer編)
- React hooksを基礎から理解する (useCallback編)
- React hooksを基礎から理解する (useMemo編)
- React hooksを基礎から理解する (useRef編)   今ここ 今ここ
useRefとは
関数コンポーネントでは、Classコンポーネント時のref属性の代わりに、useRefを使って要素への参照を行います。
またuseRefでは、useStateのようにコンポーネント内での値を保持することが出来ます。
構文
const refObject = useRef(initialValue)
//例
const number = useRef(100);
console.log(number.current); // 100
useRefは、.currentプロパティが渡された引数(初期値はinitialValue)をrefObjectへ返します。
この引数の値が書き換え可能な.currentプロパティーの値であり、 .currentプロパティ内に保持することができます。
DOMを参照したい場合
const inputElement = useRef(null)
//例: inputElement.currentで <input type="text" /> を参照
<input ref={inputElement} type="text" />
console.log(inputElement.current); // <input type="text" />
DOMの参照例
useRefでrefオブジェクトを作成したものをref属性(HTML要素)に指定してDOMを参照しています。
const App = () => {
  const inputEl = useRef(null);
  const handleClick = () => {
    inputEl.current.focus();
    console.log("inputEl.current:", inputEl.current);
    //inputEl.current: <input type="text">
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={handleClick}>入力エリアをフォーカスする</button>
    </>
  );
};
ボタンクリックで<input type="text">がfocusされました。

参照:React公式サイト
useRefとuseStateをくらべてみる
useRefを使ってDOMを参照
useRefを利用するとtextのstate更新時にのみコンポーネントの再レンダリングが発生します。
const App = () => {
  const inputEl = useRef(null);
  const [text, setText] = useState("");
  const handleClick = () => {
    setText(inputEl.current.value);
  };
  console.log("レンダリング!!");
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={handleClick}>set text</button>
      <p>テキスト : {text}</p>
    </>
  );
};
 ※ コンソールに表示される文字列: (誤り) 描画!! => (正) レンダリング!!
※ コンソールに表示される文字列: (誤り) 描画!! => (正) レンダリング!!
useStateを使ってDOMを参照
入力中の文字列をステートinputElementに格納、ボタンが押された時にsetText(inputElement)でtextstateへ代入することでuseRefを使った時と同じ挙動にしています。この場合、textとinputElementのstate更新時の両方でコンポーネントの再レンダリングが発生しています。
const App = () => {
  const [inputElement, setInputElement] = useState("");
  const [text, setText] = useState("");
  const handleClick = () => {
    setText(inputElement);
  };
  console.log("レンダリング!!");
  return (
    <>
      <input
        value={inputElement}
        onChange={(e) => setInputElement(e.target.value)}
        type="text"
      />
      <button onClick={handleClick}>setText</button>
      <p>テキスト : {text}</p>
    </>
  );
};
 ※ コンソールに表示される文字列: (誤り) 描画!! => (正) レンダリング!!
※ コンソールに表示される文字列: (誤り) 描画!! => (正) レンダリング!!
useStateを利用している場合はstateの変更される度にコンポーネントの再レンダリングが発生しますが、useRefは値が変更になっても、コンポーネントの再レンダリングは発生しませんでした
コンポーネントの再レンダリングはしたくないけど、内部に保持している値だけを更新したい場合は、保持したい値をuseStateではなく、useRefを利用するのが良さそうです。
