🍒
useRefの基本と使い方
useRefは、React 16.8から導入された、再レンダリングなしで値やDOM要素を更新できるReactフック。
「DOMに直接アクセスしたいとき」「再レンダリングなしで値を保持・更新したいとき」「前回の値や状態を記録しておきたいとき」などに便利。
使い方は2種類ある。
再レンダリングなしで値を保持・更新
- .currentで操作する。
- 何度でも変更でき、再レンダリングは起きない。
- useStateを使うと、値を変更するたびに再レンダリングが走り、状態の更新が遅延(非同期)して正しい値が取れないことがある。このようなときにuseRefを使える。
import { useRef, useState } from 'react';
const Component = () => {
// 再レンダリングなしで値を保持・更新できる
const inputValueRef = useRef<string>('');
const [savedValue, setSavedValue] = useState('');
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
inputValueRef.current = e.target.value;
};
const handleSave = () => {
setSavedValue(inputValueRef.current);
};
return (
<div>
<input type="text" onChange={handleChange} />
<button onClick={handleSave}>保存</button>
<div>保存された値: {savedValue}</div>
</div>
);
};
export default Component;
DOM操作で使う
- DOM要素に直接アクセスできる。
- focus() を使ってフォーカスを当てるなど、直接操作をしたいときに便利。
- イベントや条件に応じて、手動でDOMを操作できる。
import { useRef } from 'react';
const Component = () => {
const inputRef = useRef<HTMLInputElement>(null);
const handleFocus = () => {
// input要素にフォーカスを当てる
inputRef.current?.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={handleFocus}>フォーカスを当てる</button>
</div>
);
};
export default Component;
注意
「値の保持」と「DOM要素の参照」は、useRefを別々に作成する必要がある。同じuseRefで両方の用途を同時に扱うことはできない。
値を保持・更新の派生: 関数を動的に保持することもできる
- 動的に関数を入れ替えたいときに使える。
- 再レンダリングなしで関数を保持できる。
最新の関数を保持し、常にそれを実行する例
import { useEffect, useRef } from 'react';
const Component = () => {
const handlerRef = useRef<() => void>(() => {});
const handleClick = () => {
console.log('最新のクリック処理!');
};
// 毎回最新の関数をhandlerRefに入れておく
useEffect(() => {
handlerRef.current = handleClick;
});
useEffect(() => {
const interval = setInterval(() => {
handlerRef.current(); // 常に最新の関数が呼ばれる
}, 1000);
return () => clearInterval(interval);
}, []);
return <div>何かのUI</div>;
};
Discussion