zukucode
主にWEB関連の情報を技術メモとして発信しています。

Reactで兄弟コンポーネントの状態を共有する

検索欄に入力した文字列を、別の一覧コンポーネントでも使いたい場合があります。兄弟同士で別々にstateを持つと値がずれるため、共通の親にstateを置きます。

親で値を管理する

import { useState } from 'react';

type SearchInputProps = {
  value: string;
  onChange: (value: string) => void;
};

const SearchInput = ({ value, onChange }: SearchInputProps) => (
  <input value={value} onChange={(event) => onChange(event.target.value)} />
);

const ResultCount = ({ count }: { count: number }) => <p>{count}件</p>;

export const ProductSearch = () => {
  const [query, setQuery] = useState('');
  const products = ['ノート', 'ペン', '消しゴム'];
  const filtered = products.filter((name) => name.includes(query));

  return (
    <>
      <SearchInput value={query} onChange={setQuery} />
      <ResultCount count={filtered.length} />
      <ul>{filtered.map((name) => <li key={name}>{name}</li>)}</ul>
    </>
  );
};

入力欄は値を受け取り、変更を親へ通知します。一覧と件数は親が持つ同じ値から計算されます。

filteredqueryproductsから計算できるので、別のstateへ保存しません。両方をstateにすると、入力値だけ更新して絞り込み結果の更新を忘れるなど、値が食い違う経路が増えます。

どこまで持ち上げるか

stateは、それを必要とするコンポーネントに最も近い共通の親へ置きます。アプリ全体で使わない値までグローバル状態にする必要はありません。

例えば検索欄の開閉だけをSearchInputが使うなら、その開閉状態は子の中に残して構いません。共有したい値だけ持ち上げると、親の責務が増えすぎません。子の数が増えてpropsを何層も中継するようになってから、Contextなどを検討します。


関連記事

  • TypeScript i18nextの動的な翻訳キーを抽出対象に含める

    i18nextでステータスに応じた文言を表示する場合、翻訳キーを動的に切り替えることがあります。ただし、実行時に正しく表示できることと、翻訳キーの抽出ツールが使用箇所を検出できることは別です。今回は、...


  • React useStateで入力フォームを作成する

    Reactでテキストボックスに入力した値を使用するには、useStateで値を保持します。今回は名前とメールアドレスを入力し、送信ボタンを押すと入力内容を表示するフォームを作成します。この例では入力値...


  • React useStateで一覧の追加と削除を行う

    Reactで一覧を表示するときは、配列をuseStateへ保存できます。今回は簡単な買い物リストを作り、項目の追加と削除を行います。配列のpushやspliceで既存のstateを直接変更するのではな...


  • React useEffectで無限ループが発生するときに確認すること

    ReactのuseEffectを利用したときに無限ループが発生してしまうことがあります。特に注意したいのが、ESLintのreact-hooks/exhaustive-depsで表示された警告をUpd...


  • React useEffectの後片付けでイベント登録を解除する

    画面の幅が変わったときに表示を更新したい場合、ブラウザのresizeイベントを登録できます。登録したままにすると、コンポーネントが不要になったあとも処理が残るため、useEffectの後片付けを用意し...


  • React 関数コンポーネントにプロパティを設定する

    React+TypeScriptで作成した関数コンポーネントにプロパティを設定する方法を紹介します。以下は送信ボタンのコンポーネントを作成しています。isSubmittingというプロパティを用意して...


  • React useStateでselectの選択値を取得する

    Reactでプルダウンの選択値を扱うには、selectのvalueとonChangeを使用します。DOMから取得するvalueは、数値の選択肢を表示していても文字列です。選択値をそのまま識別子として扱...


  • React react-router-domの基本的な使い方

    React+TypeScriptのプロジェクトにreact-router-domを導入してSPAのアプリケーションを作成する方法を紹介します。まずはreact-router-domのパッケージをインス...


  • react-router-dom ページごとにファイルを分割する

    react-router-domでシングルアプリケーションを作成していると、ページ数が増えるにしたがって作成されるjsファイルのファイルサイズもどんどん増えていきます。ページごとにファイルを分割し、そ...


  • react-router-domでプログラムから画面遷移を行う

    react-router-domでプログラムから画面遷移を行う方法を紹介します。history.psuh(遷移先URL)の形式で実行すると、画面遷移を行えます。historyはreact-router...