1. ホーム
  2. javascript

[解決済み] 子コンポーネントの内部からReact Contextを更新するにはどうすればよいですか?

2022-04-20 12:56:54

質問

コンテキストに以下のような言語設定があります。

class LanguageProvider extends Component {
  static childContextTypes = {
    langConfig: PropTypes.object,
  };

  getChildContext() {
    return { langConfig: 'en' };
  }

  render() {
    return this.props.children;
  }
}

export default LanguageProvider;

私のアプリケーションコードは以下のようなものになります。

<LanguageProvider>
  <App>
    <MyPage />
  </App>
</LanguageProvider>

私のページには、言語を切り替えるコンポーネントがあります。

<MyPage>
  <LanguageSwitcher/>
</MyPage>

LanguageSwitcher この中で MyPage のように言語を'jp'に変更するために、コンテキストを更新する必要があります。

class LanguageSwitcher extends Component {
  static contextTypes = {
    langConfig: PropTypes.object,
  };

  updateLanguage() {
    //Here I need to update the langConfig to 'jp' 
  }

  render() {
    return <button onClick={this.updateLanguage}>Change Language</button>;
  }
}

export default LanguageSwitcher;

LanguageSwitcherコンポーネントの内部からコンテキストを更新するには?

解決方法は?

フックを使用する

フックは 16.8.0 で導入されました。したがって、以下のコードには最低でも 16.8.0 が必要です (クラスコンポーネントの例については下にスクロールしてください)。 CodeSandboxデモ

1. 動的コンテキストの親状態の設定

まず、コンシューマに渡す動的なコンテキストを用意するために、親の状態を使うことにする。こうすることで、単一の真実のソースを確保することができる。例えば、親アプリは次のようになる。

const App = () => {
  const [language, setLanguage] = useState("en");
  const value = { language, setLanguage };

  return (
    ...
  );
};

language が格納されている状態です。の両方を渡します。 language とセッター関数 setLanguage は、後でコンテキストを経由して

2. コンテキストの作成

次に、このような言語コンテキストを作成しました。

// set the defaults
const LanguageContext = React.createContext({
  language: "en",
  setLanguage: () => {}
});

ここでは language ('en') と setLanguage この関数は、コンテキストプロバイダからコンシューマに送信されます。これらはあくまでデフォルトであり、親コンポーネントでプロバイダコンポーネントを使用する際にその値を提供することになります。 App .

LanguageContext は、フックを使ってもクラスベースのコンポーネントを使っても同じです。

3. コンテキストコンシューマの作成

言語スイッチャーに言語を設定させるためには、コンテキストを介して言語セッター関数にアクセスできる必要があります。以下のような感じです.

const LanguageSwitcher = () => {
  const { language, setLanguage } = useContext(LanguageContext);
  return (
    <button onClick={() => setLanguage("jp")}>
      Switch Language (Current: {language})
    </button>
  );
};

ここでは言語を「jp」に設定しているだけですが、独自のロジックで言語を設定することも可能でしょう。

4. プロバイダでコンシューマを包む

ここで、言語スイッチャーコンポーネントを LanguageContext.Provider そして、より深いレベルにコンテキストを介して送信される必要がある値を渡します。以下は、私の親である App のように見える。

const App = () => {
  const [language, setLanguage] = useState("en");
  const value = { language, setLanguage };

  return (
    <LanguageContext.Provider value={value}>
      <h2>Current Language: {language}</h2>
      <p>Click button to change to jp</p>
      <div>
        {/* Can be nested */}
        <LanguageSwitcher />
      </div>
    </LanguageContext.Provider>
  );
};

これで、言語スイッチャーがクリックされるたびに、コンテキストが動的に更新されるようになりました。

CodeSandboxデモ

クラスコンポーネントの使用

最新の コンテキストAPI は React 16.3 で導入され、動的なコンテキストを持つための素晴らしい方法を提供します。以下のコードでは、最低でも16.3.0が必要です。 コードサンドボックスデモ

1. 動的コンテキストの親状態の設定

まず、コンシューマに渡す動的なコンテキストを用意するために、親の状態を使うことにする。こうすることで、単一の真実のソースを確保することができる。例えば、親アプリは次のようになる。

class App extends Component {
  setLanguage = language => {
    this.setState({ language });
  };

  state = {
    language: "en",
    setLanguage: this.setLanguage
  };

  ...
}

language は言語セッターメソッドとともにステートに格納されますが、これはステートツリーの外に置いてもかまいません.

2. コンテキストの作成

次に、このような言語コンテキストを作成しました。

// set the defaults
const LanguageContext = React.createContext({
  language: "en",
  setLanguage: () => {}
});

ここでは language ('en') と setLanguage この関数は、コンテキストプロバイダからコンシューマに送信されます。これらはあくまでデフォルトであり、親コンポーネントでプロバイダコンポーネントを使用する際にその値を提供することになります。 App .

3. コンテキストコンシューマの作成

言語スイッチャーに言語を設定させるためには、コンテキストを介して言語セッター関数にアクセスできる必要があります。以下のような感じです.

class LanguageSwitcher extends Component {
  render() {
    return (
      <LanguageContext.Consumer>
        {({ language, setLanguage }) => (
          <button onClick={() => setLanguage("jp")}>
            Switch Language (Current: {language})
          </button>
        )}
      </LanguageContext.Consumer>
    );
  }
}

ここでは言語を「jp」に設定しているだけですが、独自のロジックで言語を設定することも可能でしょう。

4. プロバイダでコンシューマを包む

ここで、言語スイッチャーコンポーネントを LanguageContext.Provider そして、より深いレベルにコンテキストを介して送信される必要がある値を渡します。以下は、私の親である App のように見える。

class App extends Component {
  setLanguage = language => {
    this.setState({ language });
  };

  state = {
    language: "en",
    setLanguage: this.setLanguage
  };

  render() {
    return (
      <LanguageContext.Provider value={this.state}>
        <h2>Current Language: {this.state.language}</h2>
        <p>Click button to change to jp</p>
        <div>
          {/* Can be nested */}
          <LanguageSwitcher />
        </div>
      </LanguageContext.Provider>
    );
  }
}

これで、言語スイッチャーがクリックされるたびに、コンテキストが動的に更新されるようになりました。

CodeSandboxデモ