web-dev-qa-db-ja.com

Reactフックとメモを使用しているときに子コンポーネントが再レンダリングされないようにする方法は?

Reactフックを試してみましたが、親コンポーネントが再レンダリングされたときに、子コンポーネントが再レンダリングされないようにするにはどうすればよいか疑問に思っています。 componentDidUpdate。私の問題は、親コンポーネントの状態を変更するために子コンポーネントで呼び出しているクリックハンドラーに起因するようです。関数は親コンポーネントで作成されるため、各親レンダーで新しく作成されますこれにより、子コンポーネントのプロップ変更がトリガーされ、子が再レンダリングされます(I think)。状況を説明するためのサンプルコードを次に示します。

function Parent() {
    const [item, setItem] = useState({ name: "item", value: 0 });

    const handleChangeItem = () => {
        const newValue = item.value + 1;
        setItem({ ...item, value: newValue });
    };

    return <Child item={item} changeItem={handleChangeItem} />;
}

const Child = React.memo(function Child({ item, changeItem }) {
    function handleClick(){
        changeItem();
    }
    return (
        <div>
            Name: {item.name} Value: {item.value}
            <button onClick={handleClick}>change state in parent</button>
        </div>
    );
});

親コンポーネントがレンダリングされるたびに子コンポーネントがレンダリングされないようにするにはどうすればよいですか?レンダーごとに再作成されないように、親のhandleChangeItemを別の場所に置く必要がありますか?その場合、itemから返されたsetItemおよびuseStateにどのようにアクセスしますか?

私は反応するのがかなり新しいです、そして、ちょうどフックで遊んで始めたので、私はおそらく明白な何かを見逃しています。

15
user1843640

Shubham Khatriは元の質問に正確に回答しましたが、この回答を追加して、このコールバックの問題を回避するための推奨される方法を示します。

ドキュメントから:

複数のサブ値を含む複雑な状態ロジックがある場合、useReducerは通常、useStateよりも推奨されます。また、コールバックの代わりにディスパッチを渡すことができるため、ディープアップデートをトリガーするコンポーネントのパフォーマンスを最適化できます。

https://reactjs.org/docs/hooks-reference.html#usereducer

FAQから:

大きなコンポーネントツリーでは、代替として、コンテキストを介してuseReducerからディスパッチ関数を渡すことをお勧めします...

https://reactjs.org/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down

これらすべての鍵は、レンダリングごとに作成されるコールバックとは異なり、ディスパッチが変更されないことです。

0
user1843640