2017-08-22 1 views
2

私の理解では、PureComponentはshouldComponentUpdate()を活用しており、状態と小道具の浅い比較を行っていますが、期待したものとは異なる動作をする小さな例を作成しました。PureComponentはどのように機能しますか?

例のアプリには人のリストが表示されます。各リスト項目には名前を変更する機能があります。それを試して、コードhereを調べてください。私は、以前のオブジェクトと同じ参照を持ってsetStateに戻って渡している

updateName(id, newName) { 
    const { people } = this.state 
    const idx = people.findIndex(person => person.id === id) 

    people[idx].name = newName 
    this.setState({ people }) 
    } 

対象:親コンポーネントで

は、私はこのようになります方法を持っています。この場合、このコンポーネントが浅い比較を行っている場合は更新しないでください。

第2に、私は子供のコンポーネントPersonをPureComponentからComponentに変更しました。私はまだ更新された子のみの恩恵を受けています(私は各子供のコンソールログをやっていますあなたがそれを検査したい場合はレンダリングします)。明らかに、これはReactが内部的に子どものために更新するかどうかを決めるものですが、コンポーネントが再レンダリングしていればすべてを再レンダリングすると仮定しました。

答えて

2

浅い比較を行ってもこのコンポーネントは更新されませんか?

うん。そして更新中ではありません。 Appコンポーネントのrender()メソッドは、最初のレンダリング後に再び呼び出されないことがわかります。これは、浅い比較が期待通りに機能しており、コンポーネントが(正しく)更新されていないことを意味します。

私はあなたをオフに投げ部分がPerson.prototype.handleSubmit()にこのラインであると信じて:

this.setState({ value: '' }) 

oldState.value !== newState.valueので、これは修正さPerson部品に再レンダリングトリガーされます、かどうかに関係なくPersonPureComponentかではありません。

この行を削除すると、何も更新されないことがわかります(予期している動作)。

明らかに、これはReactが更新する必要があるかどうかを内部的に判断するために内部的に行っていることです。

いいえ、子はそれ自身の状態を設定しています。親子関係はここでは無関係です。 Reactは子を直接更新します。

今後は、テストを分離する必要があります。この混乱の原因は、子どもが新しい小道具を受け取ったかどうかを判断するためにrender()メソッドに依存していたためです。しかし、render()メソッドは、子が新しい小道具を受け取り、子が新しい状態を設定するときに呼び出されます。このような状況のため

より良いテストは、componentWillReceiveProps()が呼び出されたかどうかを確認するため、画像からstateを排除されていたであろう:

componentWillReceiveProps(newProps) { 
    console.log('receiving props', newProps) 
} 

あなたはPersonコンポーネントにこれをプラグインした場合、あなたはそれが取得していないことがわかりますと呼ばれる。まさにあなたが期待している通りです。

簡潔に言えば、React.PureComponentは、あなたが思っていたとおりに動作します。

+0

優れた徹底的な答え@bowheart。簡単な説明がありますので、handleSubmitの 'this.setState({value: ''})'行に残して、上記のように 'componentWillReceiveProps'メソッドを追加すると、送信時にユーザーの名前が更新されます。状態の変更によって子要素のレンダリング関数が更新されるようになり、更新された名前が子要素に更新されたことを知らせるために 'componentWillReceiveProps'がトリガーされていないにもかかわらず、更新された名前が小道具からチェックされます。基本的に、参照は変更を反映していますが、コンポーネントに通知していません。 – captDaylight

+1

@captDaylightああ。良いキャッチ。あなたは正しいです。そのオブジェクトは新しい小道具として再び渡されませんが、それはまだ同じオブジェクトです。その参照されたオブジェクトは変更されています。 'render()'がそのオブジェクトから 'name'プロパティを読み込むとき、それは異なっています。この種の暗黙的な状態依存性は、Reactコミュニティがデータを不変に保つことに非常に堅実な理由です。 – bowheart

関連する問題