web-dev-qa-db-ja.com

Reactコンポーネントレンダーは、新しいURLをプッシュするときに複数回呼び出されます

ユーザーが左または右を押すと写真を変更するPhotoViewerを作成しています。 React、Redux、react-router、およびreact-router-reduxを使用しています。ユーザーが左または右を押すと、2つのことを行います。this.context.replace()を使用してURLを更新し、現在表示されている写真this.props.dispatch(setPhoto(photoId))を更新するアクションをディスパッチします。デバッグのために状態の変更にサブスクライブしています。

上記の各行は、新しい状態変更をトリガーします。 currentlyViewedPhotoを更新し、URLを更新すると、react-router-reduxがストア内のURLを更新するため、アクションをディスパッチするとストアが更新されます。アクションをディスパッチすると、最初の再レンダリングサイクルで、コンポーネントのrender関数が2回呼び出されます。 2回目の再レンダリングサイクルでは、コンポーネントのrender関数が1回呼び出されます。これは正常ですか?関連するコードは次のとおりです。

class PhotoViewer extends Component {
  pressLeftOrRightKey(e) {
    ... code to detect that left or right arrow was pressed ...

    // Dispatching the action triggers a state update
    // render is called once after the following line
    this.props.dispatch(setPhoto(photoId)) // assume photoId is correct

    // Changing the url triggers a state update
    // render is called twice
    this.context.router.replace(url) // assume url is correct
    return
  }

  render() {
    return (
      <div>Test</div>
    )
  }
}

function select(state) {
  return state
}

export default connect(select)(PhotoViewer)

このレンダリングは3回呼び出されるのが普通ですか? Reactは3回DOM diffを実行する必要があるため。この問題に関するその他の質問。

26
egidra

これは正常だと思います。あなたが顕著なパフォーマンスの問題を抱えていないなら、私はそれに汗をかかないでしょう。パフォーマンスが問題になり始めた場合、特定の状態の変更によってレンダリングされたコンポーネントが変更されないことが確実な場合は、 shouldComponentUpdate ライフサイクルメソッドのオーバーライドを検討できます。

編集:React.PureComponent の代わりに React.ComponentライフサイクルメソッドshouldComponentUpdateで浅い比較のみが必要な場合。詳細 こちら

23
Donald

3つの異なる段階で状態を設定している場合、コンポーネントも3回再レンダリングされます。

shouldStateUpdate()で条件付きレンダリングロジックが実装されていない限り、setState()は常に再レンダリングをトリガーします。

ソース

shouldComponentUpdate() にロジックを実装して、パフォーマンスの問題が発生した場合に不要な再レンダリングを防ぐことができます。

20
villeaka