問題: React フックとイベント リスナーを使用すると、状態コンソール ログに誤った情報が表示されます。
提供されている CodeSandbox: https://codesandbox.io/s/lrxw1wr97m を考えてみましょう。 [カードの追加] ボタンを 2 回クリックし、最初のカードの [ボタン 1] をクリックすると、コンソールには 2 枚のカードがある状態が正しく表示されます。ただし、同じカード (イベント リスナーによって処理される) の「Button2」をクリックすると、コンソールにはその状態のカードが 1 枚だけ誤って表示されます。
この問題は、CardsProvider コンポーネントと Card コンポーネントでのイベント ハンドラーの処理が異なるために発生します。 CardsProvider 機能コンポーネント内で定義されたイベント ハンドラー、handleCardClick および handleButtonClick は、コンポーネントがレンダリングされるたびに再定義されます。これは、定義された時点の状態を参照することを意味します。イベント リスナーがトリガーされると、この状態は失効する可能性があります。
一方、Card コンポーネントは useRef を使用してイベント リスナーを登録します。イベント リスナーは永続化されます。コンポーネントのライフサイクル全体にわたって。その結果、イベント リスナー関数は、コンポーネントがマウントされた時点の状態を参照し、古い状態になります。
1 つの解決策は、状態アップデーターを使用することです。囲んでいるスコープからの古い状態に依存するのではなく、引数として新しい状態を受け取る関数:
const eventListener = () => {
// Function receives fresh state
setState(freshState => freshState 1);
};
// Event listener is registered using `useEffect` to ensure it is only registered once
useEffect(() => {
// Register event listener
// ...
// Unregister event listener on component unmount
return () => {
// ...
};
}, []);
このシナリオでは、イベント リスナーは新しい状態を受け取るため、古いデータの問題は解消されます。ただし、状態アップデータ関数は不要な更新を防ぐために同じ状態を返すことができることに注意することが重要です。状態アップデータ関数内で console.log を使用して、状態の変化を観察します。
この問題に対処する別の方法には次のようなものがあります:
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3