1. ホーム
  2. reactjs

[解決済み] React: 親コンポーネントは状態変化時に変化していない子コンポーネントもすべて再レンダリングする

2023-03-06 16:02:54

質問

明確な答えが見つからないのですが、重複していないでしょうか?

私はシンプルなチャットアプリのためにReact + Reduxを使用しています。このアプリは、InputBar、MessageList、および Container コンポーネントで構成されています。コンテナーは (ご想像のとおり) 他の 2 つのコンポーネントをラップして、ストアに接続されています。自分のメッセージの状態と、現在のメッセージ(ユーザーが現在入力しているメッセージ)は、Reduxのストアに保持されています。簡略化した構造です。

class ContainerComponent extends Component {
  ...
  render() {
    return (
      <div id="message-container">
        <MessageList 
          messages={this.props.messages}
        />
        <InputBar 
          currentMessage={this.props.currentMessage}
          updateMessage={this.props.updateMessage}
          onSubmit={this.props.addMessage}
        />
      </div>
    );
  }
}

私が抱えている問題は、現在のメッセージを更新するときに発生します。現在のメッセージを更新すると、ストアを更新するアクションがトリガーされ、コンテナを通過してInputBarコンポーネントに戻るプロップが更新されます。

これは動作しますが、副作用として、これが起こるたびに MessageList コンポーネントが再レンダリングされます。MessageList は現在のメッセージを受け取らないので、更新する理由がありません。MessageList が大きくなると、現在のメッセージが更新されるたびにアプリの速度が著しく低下するため、これは大きな問題です。

私はInputBarコンポーネント内で直接現在のメッセージの状態を設定および更新しようとしました(したがって、Reduxアーキテクチャを完全に無視します)、そしてそれは問題を修正しました。

私の質問は

  • 親コンポーネントが更新された場合、Reactは常にそのコンポーネント内のすべての直接の子を更新するのでしょうか?

  • ここでは、どのようなアプローチが正しいのでしょうか?

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

<ブロッククオート

親コンポーネントが更新された場合、Reactはそのコンポーネント内のすべての直接の子を必ず更新しますか?

いいえ、Reactは以下の場合にのみコンポーネントを再レンダリングします。 shouldComponentUpdate() が返す true . デフォルトでは、このメソッドは常に true を返し、新規参入者の微妙なバグを回避します (そして William B が指摘したように、何かが変更されない限り DOM は実際に更新されないので、影響が少なくなります)。

サブコンポーネントが不必要に再レンダリングされないようにするために、サブコンポーネントに shouldComponentUpdate メソッドを実装し、そのメソッドが返すのは true を返すようにします。もし this.props.messages が常に同じ配列であれば、このように単純なものになります。

shouldComponentUpdate(nextProps) {
    return (this.props.messages !== nextProps.messages);
}

また、深い比較やメッセージIDの比較などを行いたい場合もあるでしょう、それはあなたの要件に依存します。

編集部:数年後、多くの人が機能的なコンポーネントを使用しています。もしあなたがそうであるなら、次のものをチェックアウトしたいと思うでしょう。 React.memo . デフォルトでは、機能コンポーネントは、クラスコンポーネントのデフォルトの動作と同様に、毎回再レンダリングされます。この挙動を変更するには React.memo() を使用し、オプションで areEqual() 関数を提供します。