React

ReactのContextとReducer

共有データの渡し方と、複雑なstate更新を整理する方法を学びます。

React入門の講座一覧

01

まずはStateを持ち上げる

共有したいstateを、利用するコンポーネントの共通の親へ移します。propsで値と更新関数を渡す方法は、データの流れが明確で最初に選びやすい方法です。

親から子へ渡すJSX
import { useState } from 'react';

function App() {
  const [theme, setTheme] = useState('light');
  return <Toolbar theme={theme} onChange={setTheme} />;
}

function Toolbar({ theme, onChange }) {
  return <button onClick={() => onChange('dark')}>{theme}</button>;
}
02

Contextを使う

多くの階層をまたいでテーマやログインユーザーを渡す場合はContextを使えます。React 19ではContextオブジェクトをそのままProviderとして書けます。古いReactではThemeContext.Providerを使います。

Contextを提供して読むJSX
import { createContext, useContext } from 'react';

const ThemeContext = createContext('light');

function Button() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>保存</button>;
}

function App() {
  return <ThemeContext value="dark"><Button /></ThemeContext>;
}

Providerのvalueが変わると、そのContextを読むコンポーネントが再レンダーします。Contextへ大きなオブジェクトを何でも詰め込まず、役割ごとに分けます。

03

Reducerで更新する

状態更新が増えたら、更新の種類をactionとして表し、Reducerに処理を集めます。Reducerは現在のstateとactionから次のstateを返す純粋な関数です。

カウンターReducerJSX
import { useReducer } from 'react';

function reducer(state, action) {
  switch (action.type) {
    case 'increment': return { count: state.count + 1 };
    case 'decrement': return { count: state.count - 1 };
    case 'reset': return { count: 0 };
    default: throw new Error('未知のaction');
  }
}

const [state, dispatch] = useReducer(reducer, { count: 0 });
dispatch({ type: 'increment' });

「どの操作で」「どの状態がどう変わるか」をaction名で残せるため、フォームや買い物かごなどの状態遷移をテストしやすくなります。

04

カスタムHook

複数のコンポーネントで同じstateと処理を使うときは、useで始まるカスタムHookへ切り出します。

useToggleJSX
import { useState } from 'react';

function useToggle(initial = false) {
  const [value, setValue] = useState(initial);
  const toggle = () => setValue(current => !current);
  return [value, toggle];
}

function Panel() {
  const [open, toggle] = useToggle();
  return <><button onClick={toggle}>切替</button>{open && <p>表示中</p>}</>;
}

Hookはコンポーネントや他のHookのトップレベルで呼び、条件分岐やループの中で呼びません。次はTypeScriptとNext.jsで、型とアプリ構成へ進みます。