Theo は今週、React フックの直感的でない動作についてビデオを作成しました。特に、現在の再レンダリングの前に、最後の再レンダリングの値バージョンを保持する usePrevious と呼ばれるフックのアイデアを調査しました。 1つ。古い状態と新しい状態を使用してロジックを実行する方法。
実装方法のアイデアを見たい場合は、ビデオをチェックしてください。この投稿では、usePrevious のようなフックを持つ概念的な側面を探求します。
ご覧のとおり、React にはこのようなプリミティブなフックがありません。フックが登場する以前、クラスベースの時代には、componentDidUpdate というライフサイクル メソッドがあり、以前のすべての状態とプロパティをパラメータとして取得していました。なぜフックでこの動作を維持しなかったのでしょうか?
この一連の投稿を読んでいると少し繰り返しになるかもしれませんが、ここではパラダイム シフトについて話す必要があります。
クラスでは、一部の状態が更新されたときに、派生した値を自動的に再計算する方法がありません。特定のプロパティと状態を使用して新しい値を計算している場合は、それらの一部が変更されているかどうかを自分で確認する必要があります。
このように、解決策はすべての更新で呼び出されるコールバックを用意し、以前の値をユーザーに送信することです。アプリのコードは差異をチェックし、計算された状態を新しい結果で更新します。これはクラスベースのコンポーネントの直接性であり、データの流れを完全に制御でき、計算を手動で制御する必要があります。
ここで、反応性の表現について説明します。
確認して変更を行う代わりに、式、つまり計算式のようなものを書きます。この計算は、以前のバージョンにアクセスせずに、現在の状態バージョンで実行する必要があります。
次の式を想像してください:
a = b + c b = 10 c = 20 a = 10 + 20 a = 30
この式を 100 万回使用し、b を 10 として渡し、c を 20 として渡しても、同じ結果が得られます。これは純粋な計算です。 React も同じ原理を実行します。すべての導出計算は純粋である必要があります。
しかし、なぜそれが重要なのでしょうか?
再レンダリングで作業に反応します。各サイクルでは UI の説明が生成され、現在のものと次のサイクルの違いに基づいて、DOM への変更がコミットされます。各レンダリングは、前または次のレンダリングから完全に分離されます。
UI = fn(state)
つまり、異なる状態バージョンごとに、異なる UI バージョンが得られます。ここに以前の値を追加すると、かなり混乱します。なぜなら、今では状態だけでなく、以前の状態にも依存するからです。 1 つのソース、1 つの式、1 つの結果を持つ代わりに、複数のソース、おそらくこれらのソースを処理するためのより複雑な式、および結果としての一貫性のない予測不可能な UI を持つことができます。
各レンダリングは、前の状態に基づいて異なる動作をします。そして、 usePrevious の可能な実装の一部は React の時間順序に依存しているため、これはより危険になります。
同時機能を使用すると、他のアクションを優先するために、レンダリングを警告せずに React を停止できます。 useEffect と ref に応じて、実際の前のものであっても、「以前の」レンダーの古いバージョンを保持することができます。さらに混乱が生じます。
このような式で考えてみましょう
a = b + c b = 10 c = 20 a = 10 + 20 a = 30
そのうちの 1 つの部分には優先順位があり、事前に計算する必要があります。JavaScript コードで考えてみましょう:
UI = fn(state)
これで、別々に計算できる、完全に純粋な 2 つの別々の式ができました。しかし、b の値が大きく変化し、cdResult の計算に負荷がかかる場合、どうやって解決すればよいでしょうか?覚えています!
a = b + (c - d)
これで、c または d が変更された場合に cdResult が再計算されます。
しかし、本文では前の値はないと言いましたが、あるレンダリングの計算を次のレンダリングでどのように使用できるのでしょうか?これは計算の純粋性を損ないませんか?
実際には、違います。例:
const cdResult = c - d; const a = b + cdResult;
レンダリング番号 1 にいると想像してください。c の値は 30、d の値は 20 なので、結果は 10 になります。しかし、私がそれをメモ化していると、React は私が追加した依存関係を追跡します。配列。それらの一部が変更されると、再計算されます。
const cdResult = React.useMemo(() => c - d, [c, d]); const a = b + cdResult;
しかし、彼らは変わりませんでした。 c を 30、d を 20 としてこの式を再度呼び出すと、結果として同じ 10 が得られます。レンダリング番号 2 にいて、他の変数が変更されているにもかかわらず、この計算で使用する依存関係は変更されていません。
レンダリングごとに再計算できます。これは React のデフォルトの動作ですが、同じ値を返す不必要な再計算をスキップすることも選択できるので、そのままにしました。純度を保ち、レンダリング間の分離を維持しました
しかし、前の状態、つまりユーザーのアクションを使用してロジックを実行するのに適した場所があります。もちろん、コールバックが呼び出された時点では、それが現在の状態になります。ただし、何らかのロジックに基づいて変更する必要がある状態がある場合は、そこが最適な場所です。
もちろん、usePrevious などのフックが必要になる非常に特殊なケースもありますが、フックによって引き起こされる可能性のある不一致に注意し、アプリケーションのバグを避けるために保証を追加するようにしてください。
そしてさらに重要なのは、可能であればそれを避けてください。
以上がusePrevious および同様の時間指向フックの問題の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。