この記事ではReactフックの1つである『useRef』について、
useRef
とはuseRef
の構文useRef
の使い方useRef
でDOM要素を参照する方法useRef
で値を保存する方法
などをサンプルコードや図を用いて分かりやすく説明するように心掛けています。ご参考になれば幸いです。
useRefとは
ReactのuseRef
は、Reactフックの一つで、主に「DOM要素への参照の保持」と「値の保存」の2つの目的で使われます。
- DOM要素への参照の保持
useRef
を用いると、ref
オブジェクトを作成することができます。この作成されたrefオブジェクトを、JSX内の特定のDOM要素に関連付けることで、その要素への参照を保持できます。- 直接的なDOM操作(フォーカスを設定する、特定のアニメーションを直接適用するなど)に役立ちます。
- 値の保存
useRef
で作成されたref
オブジェクトはcurrent
プロパティを介してアクセスされる値を持っており、このプロパティは更新可能で、その値が更新されてもコンポーネントの再レンダリングが起きないのが特徴です。
useRefの構文
useRef
の構文を以下に示します。
useRefの構文
const refContainer = useRef(initialValue);
refContainer
ref
オブジェクトを保持する変数です。ref
オブジェクトはcurrent
プロパティを通じて、保持している値へアクセスすることができます。
useRef
useRef
は引数としてinitialValue
を取ります。
initialValue
(省略可能)ref
オブジェクトの初期値です。省略した場合はundefined
になります。ref
オブジェクトをDOM要素に関連付ける場合には、initialValue
はnull
にします。
useRefの使い方
useRef
について、以下に示している使い方をこれから説明します。
useRef
でDOM要素を参照する方法(この使い方が圧倒的に多い)useRef
でDOM要素にフォーカスを設定するuseRef
でCSSのスタイルを変更する
useRef
で値を保存するuseRef
でタイマーを管理する
上記の使い方について順番に説明します。
useRefでDOM要素を参照する方法
useRef
でDOM要素を参照しているサンプルコードを以下に示します。この使い方が圧倒的に多いです。
import React, { useRef } from 'react';
function App() {
// useRefでrefオブジェクト(ここではinputEl)を作成し、初期値をnullとする
const inputEl = useRef(null);
const onButtonClick = () => {
// コンソールにrefオブジェクト(ここではinputEl)の値を出力
console.log(`refオブジェクトの値: ${inputEl.current.value}`);
};
return (
<>
<input type="text" ref={inputEl} defaultValue="hello" />
<button onClick={onButtonClick}>refオブジェクトの値をログ出力</button>
</>
);
}
export default App;
上記のサンプルコードについてこれから説明します。
まず、上記のサンプルコードの以下の箇所ではuseRef
をインポートしています。useRef
はインポートしなくても使えますが、インポートしない場合には、useRef()
をReact.useRef()
にする必要があります。
import React, { useRef } from 'react';
上記のサンプルコードの以下の箇所ではuseRef
でref
オブジェクトを作成しています。このコードではタイトル入力用の<input>
要素への参照を保持するref
オブジェクト(ここではinputEl
)を作成しています。ref
オブジェクトをDOM要素に関連付ける場合には、useRef
の引数をnull
にします。
const inputEl = useRef(null);
上記のサンプルコードの以下の箇所ではuseRef
で作成したref
オブジェクト(ここではinputEl
)をJSXのref
属性に設定しています。ref
オブジェクトをJSXのref
属性に設定することで、ref
オブジェクトのcurrent
プロパティ経由でDOM要素(ここでは<input>
要素)にアクセスすることができるようになります。
<input type="text" ref={inputEl} defaultValue="hello" />
上記のサンプルコードの以下の箇所では、ref
オブジェクト(ここではinputEl
)のcurrent
プロパティでDOM要素(ここでは<input>
要素)にアクセスしています。
console.log(`refオブジェクトの値: ${inputEl.current.value}`);
useRef
とref
オブジェクトとDOM要素の関係を図で表すと以下のようになります。
useRefでDOM要素にフォーカスを設定する
useRef
を使うことでDOM要素にアクセスができるため、DOM要素にフォーカスをさせることができます。サンプルコードを以下に示します。
import React, { useRef } from 'react';
function App() {
// useRefでrefオブジェクト(ここではinputEl)を作成し、初期値をnullとする
const inputEl = useRef(null);
const onButtonClick = () => {
inputEl.current.focus(); // 対象の要素をフォーカスする
};
return (
<>
<input type="text" ref={inputEl} />
<button onClick={onButtonClick}>input要素にフォーカス</button>
</>
);
}
export default App;
「input要素にフォーカス」ボタンをクリックすると、テキスト入力欄にフォーカスします。
onButtonClick
関数では、inputEl.current
でフォーカスする対象のDOM要素(ここでは<input>
要素)を参照し、その要素に対してfocus()
メソッドを実行して、フォーカス処理を行っています。
JavaScriptでdocument.getElemetById("対象のID").focus()
でフォーカスするのと同じ処理です。
useRefでCSSのスタイルを変更する
useRef
を使うことでDOM要素にアクセスができるため、対象のDOM要素をCSSでスタイル変更することができます。サンプルコードを以下に示します。
import React, { useRef } from 'react';
function App() {
// useRefでrefオブジェクト(ここではtextEl)を作成し、初期値をnullとする
const textEl = useRef(null);
const onButtonClick = () => {
textEl.current.style.color = 'red'; // テキスト(Hello)を赤色に変える
};
return (
<>
<p ref={textEl}>Hello</p>
<button onClick={onButtonClick}>Helloを赤色に変える</button>
</>
);
}
export default App;
「Helloを赤色に変える」ボタンをクリックすると、画面上に表示されている文字列Hello
の色が赤色に変わります。
useRefで値を保存する
以下に示すのは、ReactのuseRef
フックを使って値を保存し、その値を更新してもコンポーネントが再レンダリングされないサンプルコードです。
import React, { useRef } from 'react';
function App() {
// useRefでrefオブジェクト(ここではnumber)を作成し、初期値を10とする
const number = useRef(10);
const onButtonClick = () => {
// refオブジェクト(ここではnumber)の値を更新
number.current = 20;
// 設定した値を取り出す
const value = number.current;
// コンソールにrefオブジェクト(ここではnumber)を出力
console.log(`Updated number: ${number.current}`);
// コンソールに取り出した値(ここではvalue)を出力
console.log(`value: ${value}`);
};
// 画面に表示
// refオブジェクトの値を更新しても
// コンポーネントの再レンダリングを引き起こさないため、UI上の表示は初期レンダリング時の値(10)のまま
return (
<>
<p>The number is: {number.current}</p>
<button onClick={onButtonClick}>refオブジェクトの値を更新</button>
</>
);
}
export default App;
上記のサンプルコードについてこれから説明します。
上記のサンプルコードの以下の箇所ではuseRef
を用いてnumber
という名前のref
オブジェクトを作成しています。ref
オブジェクトは{current; initialValue}
の形式となっており、以下のサンプルコードでは{current: 10}
というref
オブジェクトを作成しています。
const number = useRef(10);
上記のサンプルコードの以下の箇所ではref
オブジェクトの値(number.current
)を変化させたり、ref
オブジェクトの値(number.current
)を取り出したり、ログに出力したりしています。ref
オブジェクトの値(number.current
)を変化させても再レンダリングは起こりません。
// refオブジェクト(ここではnumber)の値を更新
number.current = 20;
// 設定した値を取り出す
const value = number.current;
// コンソールにrefオブジェクト(ここではnumber)を出力
console.log(`Updated number: ${number.current}`);
useRefでタイマーを管理する
useRef
を使うことで再レンダリングを起こさずに値を変化させることができるため、タイマーを管理するのに使うことができます。サンプルコードを以下に示します。
import React, { useRef, useEffect } from 'react';
function App() {
const intervalRef = useRef();
useEffect(() => {
const id = setInterval(() => {
// タイマーのコード(1秒毎にログ出力している)
console.log(Date());
}, 1000);
intervalRef.current = id;
return () => {
clearInterval(intervalRef.current);
};
}, []);
return <div>Timer is running</div>;
}
export default App;
useRef
で作成したref
オブジェクト(ここではintervalRef
)は、setInterval
によって生成されるタイマーIDを保持するために使われます。
useEffect
は第二引数に空の配列[]
を渡すことで、コンポーネントがマウントされた後に一度だけ実行されます。この中で、setInterval
関数が呼び出し、1秒ごとに指定された処理(ここではログ出力)を実行しています。setInterval
から返されるタイマーIDはref
オブジェクト(ここではintervalRef
)のcurrent
プロパティに保存しています。
useEffect
のクリーンアップ関数(return
で指定された関数)は、コンポーネントのアンマウント時に実行されます。ここではclearInterval
関数を使ってタイマーを停止しています。これにより、コンポーネントが不要になった後もタイマーが実行され続けることを防ぎ、メモリリークを避けることができます。
本記事のまとめ
この記事ではReactフックの1つである『useRef』について、以下の内容を説明しました。
useRef
とはuseRef
の構文useRef
の使い方useRef
でDOM要素を参照する方法useRef
で値を保存する方法
お読み頂きありがとうございました。