●目次
ReactのuseRefは、DOMの直接操作や、レンダリングに影響しない一時的なデータの保存に非常に便利なフックです。
本記事では、useRefの基礎から使い所、useStateとの違い、実践的な活用例までを網羅的にわかりやすく解説します。
useRefとは?(定義と特徴)
useRefは、「参照(Reference)」を作成するためのフックです。
通常、状態管理にはuseStateを使いますが、useRefは再レンダリングを発生させずにデータを保持したい場合に使います。
JS
const ref = useRef(初期値);
- 再レンダリングを引き起こさない:
useRefで保持した値が変化しても、コンポーネントは再レンダリングされません。
.currentプロパティ:useRefはオブジェクトを返し、その中の.currentプロパティに値を保持します。
useRefとuseStateの違い
useRef | useState |
|---|---|
| 再レンダリングしない | 再レンダリングする |
ref.current(値)を直接更新 | セッター関数を使用して 値を更新 |
| 用途: ・値の保持 ・DOM操作 | 用途: ・状態管理 ・画面の再描画 |
useRefの基本的な使い方(値の保持)
useRef(0):初期値を0に設定した参照を作成します。countRef.current:現在の値を取得または更新します。- コンソールにクリック回数が表示されますが、画面上の表示は変わりません。
App.jsx
import React, { useRef } from 'react';
function App() {
const countRef = useRef(0);
const handleClick = () => {
countRef.current += 1;
console.log(`クリック回数: ${countRef.current}`);
};
return (
<div>
<button onClick={handleClick}>クリックしてね!</button>
</div>
);
}
export default App;
useRefでDOM要素へのアクセス
useRefは、直接DOM要素にアクセスしたい場合にも使われます。
input ref={inputRef} /:input要素に参照を設定します。inputRef.current.focus():input要素にフォーカスを当てます。
App.jsx
import React, { useRef } from 'react';
function App() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>フォーカスを当てる</button>
</div>
);
}
export default App;
実践的な例:タイマーの作成
- 「開始」ボタンを押すと1秒ごとにカウントアップ
- 「停止」ボタンでタイマーを止める
Timer.jsx
import React, { useRef, useState } from 'react';
function Timer() {
const [time, setTime] = useState(0);
const timerRef = useRef(null);
// タイマーを開始する関数
const startTimer = () => {
if (timerRef.current !== null) return;
timerRef.current = setInterval(() => {
setTime((prev) => prev + 1);
}, 1000);
};
// タイマーを停止する関数
const stopTimer = () => {
clearInterval(timerRef.current);
timerRef.current = null;
};
return (
<div>
<h1>時間: {time}秒</h1>
<button onClick={startTimer}>開始</button>
<button onClick={stopTimer}>停止</button>
</div>
);
}
export default Timer;
状態と参照の定義
time:表示用の状態。更新されるたびに画面が再描画されるtimerRef:タイマーIDを保存。再描画は不要なのでuseRefで管理
JS
const [time, setTime] = useState(0);
const timerRef = useRef(null);
タイマーの開始処理・タイマーの停止処理
- 2重起動を防止するため、
timerRef.current !== nullなら処理しない- すでにタイマーが動いていたらスキップ(2重起動を防止)
setIntervalで1秒ごとにsetTime()を実行(timeが+1)setIntervalの返り値(ID)をtimerRef.currentに保存
JS
const startTimer = () => {
if (timerRef.current !== null) return;
timerRef.current = setInterval(() => {
setTime((prev) => prev + 1);
}, 1000);
};
clearInterval()でタイマー停止(引数はtimer ID)timerRef.currentをnullに戻すことで、再びstartTimer()を使える状態にする
JS
const stopTimer = () => {
clearInterval(timerRef.current);
timerRef.current = null;
};
JSX部分(UI)
- 秒数をリアルタイムに表示(
timeはstateなので再レンダリングされる) - ボタン操作で関数を発火
JS
<h1>時間: {time}秒</h1>
<button onClick={startTimer}>開始</button>
<button onClick={stopTimer}>停止</button>
まとめ
useRefはレンダリングに影響しない変数・参照を管理するためのReactフック- DOM要素へのアクセス、値の一時保存、クリーンアップ対象の管理など幅広く活用可能
useStateと明確に使い分けることで、パフォーマンスの高いUI構築が実現できます