LoginSignup
0
1

More than 3 years have passed since last update.

useRef を書きながら学ぶ を書きながら学ぶ(React Hooks 入門シリーズ 3/6)

Last updated at Posted at 2021-02-02

ロードマップ

React 16.8 で追加された機能であるReactのHooksについて書いてあります。

書きながら学ぶ React Hooks 入門シリーズとして書き下ろしました。

はじめに

Reactの組み込みフックであるとuseRefの説明をします。

useRef とは

ref オブジェクト ( React.createRef の戻り値 ) を返すフックです。これを利用することで、DOMの参照や、コンポーネント内で値を保持できます。

値を保持する と言う点は useState と同じですが、異なる点は、useRef で生成した値を更新してもコンポーネントは再レンダリングされないことです。

なので、レンダリングには関係ない state を扱いたい時(例:コンポーネント内で値を保持したいが、値を更新してもコンポーネントを再レンダリングしたくない時)などに利用します。

構文

const refオブジェクト = useRef(初期値)

引数に渡した値が、refオブジェクトのカレントプロパティの値になります。

再度になりますが、refオブジェクトは更新しても再レンダリングされません。

今回は、useRefの主な活用方法を2つ紹介します

活用方法1...JSX内のノードに対してミュータブルな状態にしてアクションを起こせる状態にする

初回レンダリング時に、inputフィールドにFocusされるモノを作成します。

サンプルコード
App.js
import React from "react";
import Input from "./components/Input";

const App = () => {
  return (
    <div className="App">
      <p>useRef</p>
      <Input />
    </div>
  );
};

export default App;
/components/Input.js
import React, { useEffect, useRef } from "react";

const Input = () => {
  // useRefを使ってRefオブジェクトを作成。初期値はnull
  const inputRef = useRef(null);
  useEffect(() => inputRef.current.focus(), []);
  // useRefによって作成されたRefオブジェクトをInputフィールドのrefプロパティに持たせることによって
  // refオブジェクトのカレントプロパティ内にInputノードが格納されてアクセス可能になります
  return <input ref={inputRef} type="text" />;
};

export default Input;

補足として、useRefとして作成されたオブジェクトはすでにカレントプロパティを持っていて、useRef(初期値)で渡したnullがそれです。

ad59451e249a01452b0bbdb979f4b3c5.gif

リロードしても、初めからInputフィールドにフォーカスが当たっていることが分かります。

このように、JSX内のノードに対してミュータブルな状態にしてアクションを起こせる状態にすることがuseRefの1つの活用方法です。

活用方法2...クロージャ内で宣言された値へアクセスしたい場合の活用方法

1秒ごとに保持する値を更新させ、
ボタンクリックアクションでその更新を止めたい時どうやるか?
useRefを活用して作成します。

サンプルコード
App.js
import React from "react";
import Count from "./components/Count";

const App = () => {
  return (
    <div className="App">
      <p>useRef</p>
      <Count />
    </div>
  );
};

export default App;
/components/Count.js
import React, { useState, useEffect, useRef } from "react";

const Count = () => {
  // カウントのためのState
  const [count, setCount] = useState(0);
  const intervalRef = useRef();
  // ライフサイクルメソッドの中に組み込みたいのでuseEffect
  useEffect(() => {
    intervalRef.current = setInterval(() => {
      setCount((prevCount) => prevCount + 1);
    }, 1000);
    // アンマウント時の処理
    return () => {
      clearInterval(intervalRef.current);
    };
  }, []);
  return (
    <div className="Count">
      <p>{count}</p>
      <button
        onClick={() => {
          // setIntervalを実行するuseRefのカレントプロパティに入れることで
          // onClick次の処理として使えるようになる
          // useEffect 内のローカル変数として使われるとここからはアクセスできないけど
          // intervalRef.current だとアクセスが可能になる
          clearInterval(intervalRef.current);
        }}
      >
        Stop
      </button>
    </div>
  );
};

export default Count;

eeb77af50ca0a7b5880348e728f1b0eb.gif

今回は以上です。

参考

0
1
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
0
1