Help us understand the problem. What is going on with this article?

React hooksを基礎から理解する (useRef編)

React hooksとは

React 16.8 で追加された新機能です。
クラスを書かなくても、 stateなどのReactの機能を、関数コンポーネントでシンプルに扱えるようになりました。

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)

//例
<input ref={inputElement} type="text" />
console.log(inputElement); // current: null
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を使った時と同じ挙動にしています。この場合、textinputElementの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は値が変更になっても、コンポーネントの再描画が発生しませんでした:relaxed:

seira
エイチームライフスタイルのフロントエンドデザイナ。 最近はReact, Rails, php, jQuery Sass, Photoshop, Figmaなどを触っています。
life-a-tm
人生のイベントや日常生活に密着した比較サイト、情報サイト等様々なウェブサービスを企画・開発・運営
https://life.a-tm.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away