LoginSignup
362
201

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-11-23

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を利用するのが良さそうです。

362
201
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
362
201