useRef
と useState
は、React の Hooks の中で非常に一般的に使用されるものですが、それぞれ異なる目的と動作特性を持っています。以下に、それぞれの違いを概説します。
useState
- 目的: コンポーネントの状態を保持・管理するために使用します。
-
動作:
-
useState
は、初期値を受け取り、現在の状態値とその状態を更新する関数をペアで返します。 - 状態の更新関数を呼び出すと、コンポーネントは再レンダリングされます。
-
-
使用例:
const [count, setCount] = useState(0);
useRef
-
目的:
- DOM 要素への参照を保持するため。
- 任意の可変な値(re-render に影響を与えずに保持される)を保持するため。
-
動作:
-
useRef
は、引数として与えられた初期値を持つref
オブジェクトを返します。 -
ref
オブジェクトのcurrent
プロパティを通じて、保持された値にアクセスすることができます。 -
ref
オブジェクトの値(current
プロパティの値)が変更されても、コンポーネントは再レンダリングされません。
-
-
使用例:
const inputRef = useRef(null);
主な違い
-
再レンダリング:
-
useState
の状態が変更されると、コンポーネントは再レンダリングされます。 -
useRef
のcurrent
値が変更されても、コンポーネントは再レンダリングされません。
-
-
用途:
-
useState
は、コンポーネントの状態の管理・変更を行うために使用されます。 -
useRef
は、DOM 要素への参照や、再レンダリングを引き起こさない任意の値を保持するために使用されます。
-
この2つの Hook は異なる目的と動作特性を持っているため、必要に応じて適切なものを選択して使用することが重要です。
useRefはどんなユースケースで使いますか?
useRef
は多岐にわたるユースケースで使用されます。以下に、主な使用シナリオとその例を挙げます:
-
DOM 要素への参照:
- 特定の DOM 要素に直接アクセスしたいときに使用します。
- 例: インプットフィールドに自動的にフォーカスを当てる、DOM 要素のサイズや位置を取得するなど。
const inputRef = useRef(null); useEffect(() => { inputRef.current.focus(); }, []); return <input ref={inputRef} />;
-
以前の state や props の値の保持:
- コンポーネントの再レンダリングに影響を与えずに前の値を保持したい場合に使用します。
const count = useState(0); const prevCountRef = useRef(); useEffect(() => { prevCountRef.current = count; }, [count]); // どこかで prevCountRef.current を使用して前の count 値にアクセスする
-
外部ライブラリやインスタンスの保持:
- たとえば、外部ライブラリが生成するインスタンスや、タイマーの ID などを保持するために使用します。
const animationInstance = useRef(null); useEffect(() => { animationInstance.current = new SomeAnimationLibrary(); return () => { animationInstance.current.destroy(); }; }, []);
-
変更をトリガーしない変数の保持:
- コンポーネントの再レンダリングを引き起こさない変数を持つ場合に使用します。この変数はコンポーネントライフサイクル全体で生き続けます。
const renderCount = useRef(0); useEffect(() => { renderCount.current = renderCount.current + 1; }); // どこかで renderCount.current を使用してレンダリングの回数にアクセスする
-
コールバック関数内での安定した参照:
- 頻繁に変更される可能性があるコールバック内で、安定した参照を持つ必要がある場合に使用します。
const callbackRef = useRef(callback); useEffect(() => { callbackRef.current = callback; }, [callback]); useEffect(() => { const interval = setInterval(() => { callbackRef.current(); }, 1000); return () => clearInterval(interval); }, []);
これらの例は useRef
の一般的なユースケースの一部です。実際には、さまざまな状況や要件に応じて、このフックを使用して多くのことを実現することができます。