React で状態を子コンポーネントに渡す

Irakli Tchigladze 2023年6月21日
  1. 状態オブジェクトの目的
  2. 親コンポーネントから子コンポーネントにデータを渡す
  3. React で状態を子コンポーネントに渡す
  4. 状態を子コンポーネントに渡すコンテキスト API
React で状態を子コンポーネントに渡す

フロントエンド開発者は、多くの場合、Web アプリケーションの動的機能を維持するために、クライアント側で状態パターンをセットアップする必要があります。 これはフレームワークなしで可能ですが、多くの労力が必要です。

React には内部状態システムがあり、状態管理に関連する多くの問題が解消されます。

状態オブジェクトの目的

React では、状態を使用して、外部データ、ユーザー入力、および変更される可能性のあるその他の値を保存します。 たとえば、特定の状態値を更新するテキスト入力を使用して、JSX で状態値を参照および表示できます。

したがって、入力によって状態が更新され、その状態を参照して値が表示されます。 状態の値を変更すると、再レンダリングがトリガーされます。

親コンポーネントから子コンポーネントにデータを渡す

親から子に状態を渡す最も一般的で簡単な方法は、props を使用して手動で行うことです。 ツリーの最上部にあるコンポーネントからその直接の子まで、その子はそれを受け取り、props を介してそれを自身の子に渡します。というように、最終的な目的地に到達するまで続きます。

例を見てみましょう:

export default function App() {
  return (
    <div className="App">
      <Box number={11} />
      <Box number={15} />
      <Box number={18} />
    </div>
  );
}
function Box(props) {
  return <div>{props.number}</div>;
}

親から子へと価値を伝えてきました。 この場合、親から直接の子まで、1つのレベルだけを渡す必要があります。

子コンポーネントに、独自の子を持つ独自の子コンポーネントがある場合、親から子にデータを渡すのに時間がかかる可能性があります。

場合によっては、このデータを使用しない子コンポーネントにデータを渡すことがあります。 これを支柱掘削といいます。

自分がそれを頻繁に行っていることに気付いた場合は、代替手段を探す必要があります。

React で状態を子コンポーネントに渡す

React の公式ドキュメントでは、開発者がすべての状態データを親コンポーネントに保存することを推奨しています。 この慣行は、Single Source of Truth と呼ばれます。 子コンポーネントには、テキスト ボックスなどの入力要素を含めることができます。

React では、親コンポーネントの状態を更新する関数への参照を渡すことができます。 子コンポーネントでこの関数への参照を呼び出して、この子コンポーネントにローカルな値に基づいて親コンポーネントの状態を更新できます。

ほとんどの場合、React Web アプリはコンポーネント ツリーとして構造化されています。 複数の子を持つ親コンポーネントがあります。

これらの子のそれぞれは、独自の複数の子を持つことができ、コンポーネント ツリーには数十のレベルが存在する可能性があります。 そして、重要なのはコンポーネントの再利用性です。つまり、1つのコンポーネントが数十のインスタンスを持つことができます。

React では、状態 (およびその他の値) は props オブジェクトを使用して親から子に渡されます。 これは、通常の HTML 要素に属性を設定するのと同様に機能します。

代わりに、JSX でこのカスタム属性を設定すると、子コンポーネントでその値を使用できるようになります。

状態変数を子コンポーネントに渡す例を見てみましょう。

import "./styles.css";
import { useState } from "react";
export default function App() {
  const [text, setText] = useState("");
  return (
    <div className="App">
      <input type="Text" onChange={(e) => setText(e.target.value)} />
      <Box paragraph={text} />
    </div>
  );
}
function Box(props) {
  return <div>{props.paragraph}</div>;
}

ライブデモ

子のコンポーネントは親にデータを渡すことができません。 このパターンは単方向データ フローと呼ばれます。

状態データは親に格納され、子のコンポーネントに渡されます。

上記の例では、1つの親と 1つの子しかありません。 このような単純なコンポーネント ツリーでは、props を使用するのが理にかなっています。 ただし、独自の子を持つ子コンポーネントが多すぎる場合、この方法は扱いにくくなります。

幸いなことに、React には別の方法があります。これを使用すると、親からの値をすべてのレベルで渡すことなく、子のコンポーネントですぐに使用できるようになります。

状態を子コンポーネントに渡すコンテキスト API

React のコンテキスト API を使用すると、開発者は props を使用せずに状態値を子コンポーネントに渡すことができます。 すべての子供がデータにアクセスできるようになります。

これは、単一のデータを多くの子コンポーネントに個別に渡すよりもはるかに簡単です。

これらの値を多くの子コンポーネントに渡す必要があると想像してください。 次のようにする必要があります。

export default function App() {
  return (
    <>
      <Child darkMode={true} />
      <Child darkMode={true} />
      <Child darkMode={true} />
    </>
  );
}

function Child ({ darkMode }) {
  return (
    <>
      <Text darkMode={theme} />
      <Video darkMode={theme} />
      <Visual darkMode={theme} />
      <Card darkMode={theme} />
    </>
  );
}

このコンポーネントでは、上部の親コンポーネントに 3つの <Child> コンポーネントがあり、<Text><Video><Visual><Card> などの子コンポーネントがあります。 . このデータをこれらの子供たちと、彼らが持つ可能性のあるすべての子供たちに渡す必要があります。

コードを見ると、このアプローチが非効率的であることが明らかになります。

テーマ データ (ダーク モード設定) やユーザー データ (認証情報) などの状態値は、子コンポーネントのビジュアルと機能をカスタマイズするために必要になる場合があります。 手動で 1つずつ渡す代わりに、React 開発者は Context API を使用して、props を介さずに状態を子コンポーネントに渡すことができます。

コンテキストを使用して状態を子コンポーネントに渡す

React ライブラリには、React 開発者がコンテキストを作成するために使用できる createContext() メソッドが含まれています。 Context API の実装を 4つの簡単なステップに分割すると、より簡単になります。

  1. createContext() メソッドを使用してコンテキストを作成します。
  2. コンテキスト プロバイダをコンポーネント ツリーにラップします。
  3. コンテキスト プロバイダーの value prop を、コンポーネント ツリー全体で共有したい値と等しくなるように設定します。
  4. useContext() フックを使用して、子コンポーネントの値にアクセスします。

サンプル コードを作成し、各手順を実行してみましょう。

まず、他のコンポーネントの親となる機能コンポーネントを定義します。 createContext() メソッドを使用して、この親コンポーネントにコンテキストを作成し、参照を dataContext 変数に格納します。

import "./styles.css";
import React from "react";
import { useState, useContext } from "react";
const dataContext = React.createContext();

export default function App() {
  const [darkMode, setDarkMode] = useState(true);
  return (
    <dataContext.Provider value={darkMode}>
      <div>
        <Child />
      </div>
    </dataContext.Provider>
  );
}
function Child() {
  return (
    <div>
      <Grandchild />
    </div>
  );
}
function Grandchild() {
  const setting = useContext(dataContext);
  console.log(setting);
  return (
    <div
      style={{
        width: 300,
        height: 300,
        backgroundColor: setting ? "black" : "white",
        color: setting ? "white" : "black"
      }}
    >
      Hello, World
    </div>
  );
}

Appコンポーネントには、独自の子コンポーネントを持つ子コンポーネントがあります。

コンテキスト プロバイダーを使用して親コンポーネント内のコンポーネント ツリー全体をラップし、コンテキスト プロバイダーに darkMode 属性を設定します。 この値は、すべての子で使用できるようになります。

子コンポーネントで useContext() フックを使用する必要があります。 これは、親コンポーネントの Context プロバイダーに設定された値を使用するために必要です。

この場合、darkMode 値を使用して、子コンポーネントに条件付きスタイルを設定します。 親コンポーネントでこの値を変更してみることができます (useState() フックに渡される初期値を変更します)。

また、コンソールに移動し、コンテキスト API を介して darkMode 状態が親から子に正常に渡されたことを確認します。

Irakli Tchigladze avatar Irakli Tchigladze avatar

Irakli is a writer who loves computers and helping people solve their technical problems. He lives in Georgia and enjoys spending time with animals.

LinkedIn

関連記事 - React State