useRefフックの型について
背景
TypeScriptでの型指定
useRefフックの型指定は、初期値の型によって異なります。
初期値がnullの場合
import { useRef } from 'react';
const ref = useRef<HTMLInputElement | null>(null);
// 後でcurrentプロパティにHTMLInputElementを代入する場合
ref.current = document.getElementById('myInput') as HTMLInputElement;
この場合、ref.current
はHTMLInputElement | null
型になります。つまり、null
またはHTMLInputElement
のいずれかになります。
初期値が特定のオブジェクトの場合
import { useRef } from 'react';
interface MyObject {
name: string;
age: number;
}
const ref = useRef<MyObject>({ name: 'Alice', age: 30 });
// 後でcurrentプロパティを別のMyObjectに更新する場合
ref.current = { name: 'Bob', age: 25 };
この場合、ref.current
はMyObject
型になります。
重要なポイント
ref.current
へのアクセスは、レンダリングサイクルの外で行うのが一般的です(例えば、イベントハンドラやuseEffectフック内)。ref.current
の型は、初期値の型によって決まります。ref.current
はミュータブルなプロパティです。つまり、直接変更することができます。
// JavaScript
const ref = useRef(null);
// 後でcurrentプロパティにHTMLInputElementを代入する場合
ref.current = document.getElementById('myInput');
TypeScript
// TypeScript
import { useRef } from 'react';
// 初期値がnullの場合
const ref = useRef<HTMLInputElement | null>(null);
// 後でcurrentプロパティにHTMLInputElementを代入する場合
ref.current = document.getElementById('myInput') as HTMLInputElement;
// 初期値が特定のオブジェクトの場合
interface MyObject {
name: string;
age: number;
}
const ref = useRef<MyObject>({ name: 'Alice', age: 30 });
// 後でcurrentプロパティを別のMyObjectに更新する場合
ref.current = { name: 'Bob', age: 25 };
解説
-
- 初期値がnullの場合
ref
の型をHTMLInputElement | null
と指定します。ref.current
はnull
またはHTMLInputElement
のいずれかになります。
- 初期値が特定のオブジェクトの場合
MyObject
インターフェースを定義します。ref
の型をMyObject
と指定します。
- 初期値がnullの場合
-
JavaScript
useRef
フックを使用して、ref
という変数を宣言します。- 初期値は
null
です。 - 後で、
ref.current
にdocument.getElementById('myInput')
で取得したHTMLInputElementを代入します。
useRef
フックは、レンダリングに直接関係しない値を保持する便利なツールですが、特定のユースケースでは、他のアプローチも検討できます。
State Hook (useState)
-
欠点
-
利点
- 値の変更をトリガーに再レンダリングが行われるため、UIの更新が自動的に行われます。
- 値の履歴を保持することができます。
-
シンプルな値の管理
もし、useRef
で管理している値が単純な値(例えば、数値や文字列)で、レンダリングに影響を与える場合、useState
フックを使用することができます。import { useState } from 'react'; const [value, setValue] = useState<number>(0); // 値の更新 setValue(newValue);
Context API
-
- グローバルな値を簡単に共有できます。
- 複雑な状態管理を簡潔に表現できます。
-
グローバルな値の共有
複数のコンポーネント間で値を共有したい場合、Context APIを使用することができます。import { createContext, useContext } from 'react'; const MyContext = createContext<number>(0); // Providerコンポーネント function MyProvider({ children }) { const [value, setValue] = useState<number>(0); return ( <MyContext.Provider value={value}> {children} </MyContext.Provider> ); } // Consumerコンポーネント function MyConsumer() { const value = useContext(MyContext); // 値の更新はProviderコンポーネントで行う }
適切な方法の選択
- レンダリングに直接関係しない値の保持
useRef
フックが適しています。 - グローバルな値の共有
Context APIが適しています。 - 単純な値の管理
useState
フックが適しています。
reactjs typescript react-hooks