この記事では、テスト ケース内、特に React の一般的な状態管理ライブラリである Zustand 内での ReactDOM.unstable_batchedUpdates の使用について検討します。また、テストを詳しく説明し、バッチ更新が不必要な再レンダリングを最小限に抑えて React のパフォーマンスを向上させる方法についても説明します。
これが調査するテストケースです:
このテスト ケースは、React のレンダリング システムで Zustand を使用するときにバッチ更新が適用できることを検証するために作成されています。
1. Zustand ストアのセットアップ: 最初のステップでは、作成関数を使用して Zustand ストアを作成します:
const useBoundStore = create( (set) => ({ count: 0, inc: () => set((state) => ({ count: state.count 1 })), }))
ここで、ストアは、0 に初期化された count プロパティとカウントをインクリメントする inc 関数を備えた単純な状態を維持します。 set 関数は、React の setState に似た、Zustand の状態を更新する方法です。
2. Counter コンポーネント: Counter コンポーネントは useBoundStore を使用して現在のカウントと inc 関数を取得します:
const { count, inc } = useBoundStore()
このコンポーネントはストアの状態をサブスクライブし、カウントが変更されると、新しい値で再レンダリングされます。
3.パフォーマンスのための ReactDOM.unstable_batchedUpdates の使用: useEffect フック内で、ReactDOM.unstable_batchedUpdates ブロック内で inc 関数が 2 回呼び出されます:
useEffect(() => { ReactDOM.unstable_batchedUpdates(() => { inc() inc() }) }, [inc])
ここで魔法が起こります。通常、inc() を呼び出すたびに個別の更新がトリガーされ、2 回のレンダリングが発生します。ただし、これらの呼び出しをunstable_batchedUpdatesでラップすることにより、Reactはそれらを1つの更新でまとめて処理できるため、レンダリングは1つだけになります。これにより、レンダリングの数が減ってパフォーマンスが最適化され、パフォーマンスが重要なアプリケーションで特に役立ちます。
4.コンポーネントのレンダリングと結果のアサート 最後に、コンポーネントがレンダリングされ、テストはカウントが 2:
に達するまで待機します。
const { findByText } = render(>, ) await findByText('count: 2')
このアサーションにより、2 回増加した後、カウントが正しく更新され、「count: 2」としてレンダリングされることが保証されます。
ReactDOM.unstable_batchedUpdates は、React によって提供されるメソッドで、複数の状態更新を 1 回のレンダリング サイクルで処理できるようにします。デフォルトでは、React はイベント ハンドラー (クリック イベントなど) 内でトリガーされた更新をバッチ処理します。つまり、ユーザー インタラクションに応じて複数の状態を更新する場合、React はコンポーネントを 1 回だけレンダリングします。ただし、イベント ハンドラーの外部 (setTimeout や useEffect 内など) では、更新は自動的にバッチ処理されません。
しかし、これは React 18 以降変更されました。以下は、react.dev から抜粋したスクリーンショットです
ドキュメントでは、タイムアウト、プロミス、ネイティブ イベント ハンドラー、またはその他のイベント内の更新は、React イベント内の更新と同じ方法でバッチ処理されると示唆されていることに注意してください。ただし、この Zustand のテスト ケースでは、バッチ更新が useEffect 内で適用されます。ここで、unstable_batchedUpdates が役立ちます。これにより、イベントドリブンのコンテキスト外であっても、React が複数の状態更新を 1 つのレンダリングにグループ化することが強制され、再レンダリングが最小限に抑えられ、パフォーマンスが向上します。
例:
unstable_batchedUpdate なし:
inc() // triggers one render inc() // triggers another render
unstable_batchedUpdate あり:
ReactDOM.unstable_batchedUpdates(() => { inc() // triggers only one render for both updates inc() })
このメソッドは React の公式パブリック API の一部ではないため「不安定」とラベル付けされていますが、パフォーマンスの最適化のためにコミュニティで今でも広く使用されています。将来的には、より安定したものになるか、React の新しい同時レンダリング機能の一部として統合される可能性があります。
面白い事実: Zustand の 4.5.5 リリースではバージョン 19.0.0-rc.0 が使用されています
Zustand は、React のコンポーネントのライフサイクルで動作する軽量の状態管理ライブラリです。 Zustand は状態の更新を効率的に処理しますが、React の反応性システムは状態が変化するたびにレンダリングをトリガーします。短期間に複数の状態変化が発生するシナリオでは、ReactDOM.unstable_batchedUpdates を使用すると、複数の再レンダリングを防ぎ、更新をバッチ処理できるため、よりスムーズで効率的なユーザー エクスペリエンスが可能になります。
提供されているテスト ケースでは、バッチ更新内で inc を 2 回呼び出すことで、カウントが 1 回だけ更新されるようになり、各更新を個別に実行する場合と比べて効率的になります。
Think Throo では、オープンソース プロジェクトで使用される高度なコードベース アーキテクチャの概念を教えることを使命としています。
Next.js/React の高度なアーキテクチャ概念を実践してコーディング スキルを 10 倍にし、ベスト プラクティスを学び、本番レベルのプロジェクトを構築します。
私たちはオープンソースです — https://github.com/thinkthroo/thinkthroo (スターを付けてください!)
コードベース アーキテクチャに基づいた高度なコースでチームのスキルを向上させます。詳細については、[email protected] までお問い合わせください。
https://github.com/pmndrs/zustand/blob/v4.5.5/tests/basic.test.tsx#L175C7-L175C39
https://dev.to/devmoustafa97/do-you-know-unstablebatchedupdates-in-react-enforce-batching-state-update-5cn2
https://dev.to/jackbuchananconroy/react-18-what-s-changed-automatic-batching-13ec
https://react.dev/blog/2022/03/08/react-18-upgrade-guide#automatic-batching
https://github.com/pmndrs/zustand/blob/v4.5.5/package.json#L246C4-L247C32
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3