組み込みの React フック

フックを用いると、コンポーネントから様々な React の機能を使えるようになります。組み込みのフックを使うこともできますし、組み合わせて自分だけのものを作ることもできます。このページでは、React に組み込まれたすべてのフックを説明します。


state フック

state を使うと、ユーザの入力などの情報をコンポーネントに「記憶」させることができます。例えば、フォームコンポーネントは入力された文字を保持し、画像ギャラリのコンポーネントは選択された画像を保持できます。

コンポーネントに state を追加するには、次のフックのいずれかを使います:

  • useState は直接的に更新できる state 変数を定義します。
  • useReducer は、リデューサ関数内に書いたロジックを用いて更新を行う state 変数を定義します。
function ImageGallery() {
const [index, setIndex] = useState(0);
// ...

コンテクストフック

コンテクストを用いると、コンポーネントは props を渡すことなく、離れた親要素から情報を取得できるようになります。例えば、アプリの最上位のコンポーネントが、現在の UI テーマをコンポーネントの階層に関係なくすべてのコンポーネントに渡すことができます。

  • useContext は、コンテクストの値を読み取り、変更を受け取れるようにします。
function Button() {
const theme = useContext(ThemeContext);
// ...

ref フック

ref を用いると、コンポーネントは DOM ノードやタイムアウト ID などの、レンダーに用いない情報を保持することができます。state と違い、ref の値を更新してもコンポーネントは再レンダーされません。ref は、React パラダイムからの「避難ハッチ」です。これらは組み込みのブラウザ API などの、React 外のシステムを取り扱うときに役立ちます。

  • useRef は ref を宣言します。useRef にはどんな値でも格納できますが、多くの場合、DOM ノードを格納するために使われます。
  • useImperativeHandle を用いると、コンポーネントが公開する ref をカスタマイズできます。これはほとんど用いられることはありません。
function Form() {
const inputRef = useRef(null);
// ...

エフェクトフック

エフェクトを使うことで、コンポーネントを外部システムに接続し、同期させることができます。これには、ネットワーク、ブラウザの DOM、アニメーション、別の UI ライブラリを使って書かれたウィジェット、その他の非 React コードの処理が含まれます。

  • useEffect は外部のシステムとコンポーネントを接続します。
function ChatRoom({ roomId }) {
useEffect(() => {
const connection = createConnection(roomId);
connection.connect();
return () => connection.disconnect();
}, [roomId]);
// ...

エフェクトは、React パラダイムからの「脱出ハッチ」です。エフェクトをアプリケーションのデータフローを調整するために使ってはいけません。外部のシステムとやりとりを行わないならば、エフェクトは必要ないかもしれません

useEffect には、実行タイミングが異なり、まれに使われることのある 2 つのバリエーションがあります:

  • useLayoutEffect はブラウザが画面を再描画する前に発火します。このフックでレイアウトを測定できます。
  • useInsertionEffect は React が DOM に変更を加える前に発火します。ライブラリは動的な CSS をこのフックで挿入できます。

パフォーマンス関連フック

再レンダーのパフォーマンスを最適化するためのよくある方法は、不要な処理を減らすことです。例えばキャッシュ済みの計算結果を再利用したり、データの変更がない場合の再レンダーをスキップしたりするよう、React に伝えることができます。

不要な計算やレンダーをスキップするためには、以下のフックを用いることができます:

  • useMemo を用いると高負荷な計算の結果をキャッシュできます。
  • useCallback を用いると、最適化済みのコンポーネントに渡すために関数定義をキャッシュしておくことができます。
function TodoList({ todos, tab, theme }) {
const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]);
// ...
}

画面の更新が実際にあるため、再レンダーをスキップできない場合もあるでしょう。その場合、同期的に行う必要があるユーザインターフェイスをブロックする更新(ユーザの文字入力など)を、ユーザインターフェイスをブロックする必要のないノンブロッキングな更新(図の更新など)から分離することで、パフォーマンスを向上することができます。

レンダーの優先度付けを行うために、以下のフックを用いることができます:

  • useTransition を用いることで、state の遷移をノンブロッキングなものとしてマークし、他の更新による割り込みを許可します。
  • useDeferredValue を用いると、UI の重要でない部分の更新を遅延させて、他の部分を先に更新させることができます。

リソース関連フック

リソース (resource) は state に入れずにコンポーネントからアクセスできます。例えばコンポーネントは Promise からメッセージを読み取ったり、コンテクストからスタイルに関する情報を読み取ったりできます。

リソースから値を読み取るには、以下のフックを用いることができます:

function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
const theme = use(ThemeContext);
// ...
}

その他のフック

これらのフックはライブラリの開発者には有用ですが、アプリケーションコードでは通常は用いられることはありません。

  • useDebugValue を用いると、React DevTools が表示するカスタムフックのラベルをカスタマイズできます。
  • useId を用いると、コンポーネントにユニークな ID を関連付けることができます。通常はアクセシビリティ API とともに使用されます。
  • useSyncExternalStore を用いると、コンポーネントは外部のストアを参照できるようになります。

独自のフック

JavaScript の関数として独自のカスタムフックを定義することもできます。