ホームページ  >  に質問  >  本文

ループベースのパラメーターを使用して React で useCallback 関数を効率的に定義する

######質問###

React では、参照識別子の不一致による単一要素の発生を避けるために、

useCallback

のようなものを使用して項目のリスト (ループ経由で作成) 内の関数を記憶する必要があることがよくあります。 -rendering... 残念ながら、これは驚くほど有効期限が切れにくいです。たとえば、次のコードを考えてみましょう:

リーリー ここで、Button

は、ant design などによって提供される外部コンポーネントです。この関数参照はインラインであるため、レンダリングごとに異なり、再レンダリングが強制されます。

A (悪い) 解決策

この問題を回避するには、別の解決策を考えます。それは、2 つのプロパティ

index={i}

onClick を受け入れる新しいコンポーネント MyButton を作成することです。単一の onClick の代わりに、パラメータ indexonClick: への呼び出しに追加します。 リーリー より良い方法が必要な理由

これは機能しますが、いくつかの理由から非常に非現実的です:

コードの混乱

リーリー しかし、まだ完璧ではありません。特に、さまざまなネスト レベルのラッパーが必要であり、新しいプロパティ (

onClick

onChange、..) をターゲットにするたびに新しいバージョンを作成する必要があります。 .)、複数のプロパティ (例: onClick

onChange

) がある場合、これは直接機能しません。これまでにこれを見たことがないので、より良い解決策があると思います。 ######編集### fast-memoize を使用するなど、さまざまなアイデアを試しましたが、結果がすべて理解できません。fast-memoize が機能する場合もあれば、失敗する場合もあります。fast-memoize が推奨される解決策であるかどうかもわかりません。このような一般的なユースケースにサードパーティのツールを使用するのは奇妙に思えます。ここで私のテストをチェックしてください https://codesandbox.io/embed/magical-dawn-67mgxp?fontsize=14&hidenavigation=1&theme=dark
P粉550823577P粉550823577299日前442

全員に返信(2)返信します

  • P粉001206492

    P粉0012064922024-01-17 12:54:38

    1. まず第一に、インデックスをパラメータ、プロップ、またはキーとして使用することはお勧めできません。最初のものを削除すると、すべての子コンポーネントが再レンダリングされるからです。
    2. また、再レンダリングを避けたい場合のシナリオに応じて、次のような参考になるアイデアがいくつかあります。
    リーリー リーリー

    ここでテスト https://codesandbox.io /s/sharp-wind-rd48q4?file=/src/App.js

    返事
    0
  • P粉916760429

    P粉9167604292024-01-17 00:55:55

    警告: 私は React の専門家ではありません (それが私の質問です!)。そのため、このソリューションが React (または-1 違います ^^)。また、他のソリューションがなぜ失敗するのかにも興味があります(たとえば、proxy-memoize(実際にはキャッシュしない場合よりも10倍時間がかかり、まったくキャッシュされません)やfast-memoize(方法によっては常にキャッシュされるわけではありません)に基づくもの)私はそれを使っています))ので、ご存知であれば知りたいです)

    私はこの問題にはあまり興味がないので、さまざまなオプション (メモリなし、外部ライブラリの使用 (高速メモリとプロキシ メモリ)、ラッパーの使用)、外部コンポーネントの使用などに対して、多数のソリューション (14!) のベンチマークを試みました。 ...

    最良の方法は、最後のボタンだけでなく、リスト の要素全体を含む新しいコンポーネント を作成することのようです。これにより、かなりクリーンなコードが可能になり (たとえリストと項目に対して 2 つのコンポーネントを作成する必要があるとしても、少なくとも意味的には意味があります)、外部ライブラリを回避し、私が試した他のすべてのものよりも効率的であるように見えます (少なくとも)私の意見(例):

    リーリー

    親コンポーネントから子コンポーネントに大量のコンテンツを転送する必要があるため、このソリューションはまだあまり好きではありませんが、これが私が得ることができる最良のソリューションのようです...

    私の試みのリストは ここ で確認できます。以下のコードを使用しました。プロファイラーからのビューは次のとおりです (技術的には、すべてのバージョン間の時間差はそれほど大きくありません (proxy-memoize を使用するバージョン 7 を除く。おそらく 10 倍ほど長く、グラフが読みにくくなっているため削除しました) , しかし、項目の描画がより複雑になる長いリストでは、この差がさらに大きくなると予想します (ここではテキストとボタンが 1 つだけあります)。すべてのバージョンがまったく同じではないことに注意してください ( を使用するもの、通常のリスト、Ant が設計したリストなど)。比較することは、同じことを行うバージョン間でのみ意味を持ちます。とにかく、私の主な関心事は、何がキャッシュされ、何がキャッシュされていないのかを確認することです。これはプロファイラーで明確に表示されます (明るい灰色のブロックがキャッシュされています)。

    もう 1 つの興味深い事実は、少なくとも単純なコンポーネント (ここではサイズ 5、テキストとボタンが 1 つだけ) の場合、改善が顕著ではない可能性があるため、覚える前にベンチマークを実行することをお勧めします。

    リーリー

    返事
    0
  • キャンセル返事