[React #03] コンポーネントのネストとデータの流れ

コンポーネント間のデータの流れ

Reactのコンポーネントは親子関係を持ちながらデータをやり取りします。

コンポーネント間でデータを渡す方法として、主にProps状態管理が使われます。Reactのデータの流れは一方向(unidirectional)です。

データが親から子へ流れることが基本となっており、アプリケーションの状態をより予測可能にし、管理しやすくします。

親から子へのデータ渡し(Props)

Reactでは、親コンポーネントから子コンポーネントにデータを渡すためにPropsを使用します。
Propsは一方向のデータフローを提供し、親コンポーネントが子コンポーネントに情報を伝達します。

これにより、Reactコンポーネントは宣言的に、データがどのように流れるかを明示的に制御できます。

親コンポーネントから子コンポーネントにデータを渡す簡単な例を見てみましょう。

function ParentComponent() {
  const message = "こんにちは、子コンポーネント!";
  return <ChildComponent greeting={message} />;
}

function ChildComponent(props) {
  return <p>{props.greeting}</p>;
}
  • Propsの使い方: 親から子へ渡すデータはpropsというプロパティを通じて渡されます。子コンポーネントはそのデータをpropsオブジェクトとして受け取り、表示に使用します。

子から親へのデータ更新(Callback関数)

子コンポーネントが親コンポーネントの状態を変更するためには、親から子コンポーネントに関数(Callback関数)を渡す方法を使用します。

子コンポーネントはその関数を呼び出して親の状態を変更します。このパターンは、ユーザーの入力やアクションによって親の状態が変更される場面でよく使われます。

以下のコードでは、親コンポーネントがhandleChangeMessageという関数を子コンポーネントに渡し、子コンポーネントがその関数を呼び出すことで親の状態を更新しています。

function ParentComponent() {
  const [message, setMessage] = useState('親からのメッセージ');

  const handleChangeMessage = (newMessage) => {
    setMessage(newMessage);
  };

  return (
    <div>
      <p>{message}</p>
      <ChildComponent onMessageChange={handleChangeMessage} />
    </div>
  );
}

function ChildComponent(props) {
  return (
    <button onClick={() => props.onMessageChange("子からの新しいメッセージ")}>
      メッセージを変更
    </button>
  );
}
  • コールバック関数の役割: 親コンポーネントが提供した関数(Callback)を子コンポーネントが呼び出し、親コンポーネントの状態を変更します。

複数のコンポーネントで状態を共有する方法

状態管理の方法は、Reactでアプリケーションが大きくなるにつれて重要になってきます。

状態が親コンポーネントに閉じていると管理が簡単ですが、複数のコンポーネント間で状態を共有する必要がある場合には、Context APIや**状態管理ライブラリ(例: Redux)**を使用します。

1. 親子間での状態共有

Reactでは、親コンポーネントで状態を管理し、その状態を子コンポーネントに渡すことで、親子間で状態を共有することができます。この場合、状態の変更は親コンポーネントで行われ、子コンポーネントはその状態を受け取って表示します。

function ParentComponent() {
  const [counter, setCounter] = useState(0);

  return (
    <div>
      <p>カウンター: {counter}</p>
      <ChildComponent counter={counter} setCounter={setCounter} />
    </div>
  );
}

function ChildComponent({ counter, setCounter }) {
  return (
    <button onClick={() => setCounter(counter + 1)}>
      カウントアップ
    </button>
  );
}

2. Context APIによる状態の共有

Context APIは、親コンポーネントから深くネストされたコンポーネント間で状態を共有するための仕組みです。
Contextを使うことで、状態をグローバルに管理し、必要な場所からアクセスすることができます。

const CounterContext = React.createContext();

function ParentComponent() {
  const [counter, setCounter] = useState(0);

  return (
    <CounterContext.Provider value={{ counter, setCounter }}>
      <ChildComponent />
    </CounterContext.Provider>
  );
}

function ChildComponent() {
  const { counter, setCounter } = useContext(CounterContext);

  return (
    <button onClick={() => setCounter(counter + 1)}>
      カウントアップ
    </button>
  );
}
  • Context API: 複数のコンポーネントで共有される状態を管理する方法で、コンポーネントツリー全体でデータを簡単に共有することができます。

3. Reduxによる状態管理

Reduxは、より大規模なアプリケーションでの状態管理に使われるライブラリです。Reduxは状態をグローバルに管理し、アプリケーション全体でアクセスできるようにします。状態の変更はアクションを通じて行われ、リデューサーが状態を更新します。

// Action
const increment = () => ({ type: 'INCREMENT' });

// Reducer
function counterReducer(state = 0, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    default:
      return state;
  }
}

// Store
const store = createStore(counterReducer);

// Component
function Counter() {
  const count = useSelector(state => state);
  const dispatch = useDispatch();
  return (
    <div>
      <p>カウント: {count}</p>
      <button onClick={() => dispatch(increment())}>カウントアップ</button>
    </div>
  );
}

まとめ

  • Propsを使って親から子へデータを渡す。
  • Callback関数を使って子から親へデータを渡し、状態を更新する。
  • Context APIReduxを使って、複数のコンポーネント間で状態を効率的に共有する。

これらを使いこなすことで、Reactのコンポーネント間でのデータのやり取りがスムーズに行えるようになります。次のステップとして、これらの理解を深め、実際に手を動かしてコードを書いてみると良いでしょう。

過去記事