本文へスキップ
BecomeCoder

Reactコース · 第5章 状態の共有と再利用 · レッスン17

カスタムフックでロジックを再利用する

ブラウザで完結

導入

「カウンターの増減」「ON/OFFの切り替え」のように、state を伴う似た処理が複数のコンポーネントで必要になることがあります。コピペで増やしていくと、直すときに全部を直す羽目になります。React では use で始まる自作の関数カスタムフック)にロジックを切り出すことで、この重複をなくせます。

説明

カスタムフックは「中で useState などのフックを呼ぶ、ふつうの関数」です。名前を use で始めるのが決まりごとで、これによって React(と ESLint)が「これはフックだ」と認識できます。

// カスタムフック:カウンターのロジックだけを持つ
function useCounter(initial = 0) {
  const [count, setCount] = React.useState(initial);
  const increment = () => setCount((c) => c + 1);
  const decrement = () => setCount((c) => c - 1);
  const reset = () => setCount(initial);
  return { count, increment, decrement, reset };
}

function Counter({ label }) {
  const { count, increment, decrement, reset } = useCounter(0);
  return (
    <div style={{ border: "1px solid #94a3b8", borderRadius: 8, padding: 12, marginBottom: 8 }}>
      <p>{label}: {count}</p>
      <button onClick={increment}>+1</button>
      <button onClick={decrement}>-1</button>
      <button onClick={reset}>リセット</button>
    </div>
  );
}

function App() {
  return (
    <div style={{ fontFamily: "system-ui", maxWidth: 320 }}>
      <Counter label="りんごの数" />
      <Counter label="みかんの数" />
    </div>
  );
}
  • useCounter の中身は、実は今まで書いてきた useState + ハンドラそのものです。それを関数として切り出しただけです。
  • <Counter label="りんごの数" /><Counter label="みかんの数" /> は、それぞれが独立して useCounter を呼んでいます。だから片方を+1しても、もう片方の数字は変わりません(ロジックは共有していますが、state そのものはコンポーネントごとに別々です)。
  • カスタムフックは値だけでなく、useEffect を含めた任意のフックの組み合わせを隠せます。「よく使う定型パターン」をまとめる場所だと考えてください。

やってみよう

useToggle(initial = false) というカスタムフック(value と、反転させる toggle を返す)を作り、ON/OFFスイッチのボタンを2つ、App に独立して置いてみましょう。

実際に動かしてみよう

下のエディタにReactのコードを書くと、右側のプレビューにその場で描画されます。`function App() { ... }` を定義すると自動で表示されます(React・useState などは React.useState の形で使えます)。本文の例を打ち込んだり書き換えたりして、表示の変化を確かめながら進めましょう。

React — ブラウザ内で実行

JSXをその場で変換して描画する学習用React環境(React18 + Babel・同梱)を読み込みます。
スクロールして表示された時点でも自動で読み込まれます。