1. ホーム
  2. javascript

新しいReact Context APIは再レンダリングを誘発するか?

2023-10-26 08:12:43

質問

新しいReact Context APIを理解しようとして、それを使って遊んでいました。Provider へのデータが更新されたときに、すべてが再レンダリングされるのは何かという、単純なケースを確認したかったのです。

確認 この小さな例はCodesandboxにあります。

では、私の例では App コンポーネントがあり、次のような状態になっています。

this.state = {
  number - A random number
  text - A static text
} 

ここから新しいReact Contextを作成し、その中に numbertext の2つの Consumers に値を渡します。 NumberText .

私の仮定では、乱数が更新されると、コンテキストが変更され、両方のコンポーネントが再レンダリングを開始するはずです。

しかし、実際には、値は更新されていますが、再レンダリングは起こっていません。

そこで、私の質問ですが

  1. コンテキストへの更新は、通常のレンダリングでは伝わらないのでしょうか?コンテキストが変更されたときに、私のログ/色の変更を見ることができないので。

  2. そのProviderへのコンシューマはすべて更新されているのか、いないのか?

どのように解決するのですか?

<ブロッククオート

コンテキストの更新は、通常のリレンダリングでは反映されないのでしょうか?私はコンテキストが変更されたときに私のログ/色の変化を見ることができないように。

コンテキスト値の更新は、プロバイダーのすべての子プロバイダーに対して再レンダリングをトリガーするのではなく、Consumer 内からレンダリングされるコンポーネントに対してのみ行われます。したがって、このケースでは、Number コンポーネントは Consumer を含んでいますが、Number コンポーネントは再レンダリングされず、むしろ Consumer 内のレンダー関数だけで、その結果、コンテキスト更新で値が変更されるのです。この方法では、すべての子コンポーネントの再レンダリングが発生しないため、非常に高いパフォーマンスを発揮します。

そのプロバイダに対するすべてのコンシューマは更新されますか、されませんか?

そのプロバイダに対するすべてのコンシューマは更新サイクルを経ますが、再レンダリングするかどうかは、reactの仮想DOM比較によって決定されます。このデモは、以下のコンソールで見ることができます。 サンドボックス

EDIT

コンポーネントはContextProviderコンポーネントの子としてレンダリングされ、インラインでレンダリングしてContextProviderの状態を更新するのではなく、ハンドラを渡していることを確認する必要があります。 ContextProvider

パフォーマンス的な使用法

App.js

  constructor() {
    super();
    this.state = {
      number: Math.random() * 100,
      text: "testing context api"
      updateNumber: this.updateNumber,
    };
  }
  render() {
    return (
      <AppContext.Provider
        value={this.state}
      >
        {this.props.children}
      </AppContext.Provider>
    );
  }

index.js

class Data extends React.Component {
  render() {
    return (
      <div>
        <h1>Welcome to React</h1>
        <Number />
        <Text />
        <TestComp />
        <AppContext.Consumer>
          {({ updateNumber }) => (
            <button onClick={updateNumber}>Change Number </button>
          )}
        </AppContext.Consumer>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <App>
    <Data />
  </App>,
  rootElement
);

パフォーマンスの低い使い方

App.js

class App extends Component {
  constructor() {
    super();
    this.state = {
      number: Math.random() * 100,
      text: "testing context api"
    };
  }

  updateNumber = () => {
    const randomNumber = Math.random() * 100;
    this.setState({ number: randomNumber });
  };

  render() {
    return (
      <AppContext.Provider value={this.state}>
        <div>
          <h1>Welcome to React</h1>
          <Number />
          <Text />
          <TestComp />
          <button onClick={this.updateNumber}>Change Number </button>
        </div>
      </AppContext.Provider>
    );
  }
}