133
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

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)

//例: 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を使った時と同じ挙動にしています。この場合、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:

コンポーネントの再レンダリングはしたくないけど、内部に保持している値だけを更新したい場合は、保持したい値をuseStateではなく、useRefを利用するのが良さそうです。

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
Sign upLogin
133
Help us understand the problem. What are the problem?