ループベースのパラメーターを使用して React で useCallback 関数を効率的に定義する
P粉550823577
P粉550823577 2024-01-16 14:06:30
0
2
391
######質問###

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

useCallback

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

リーリー ここで、Button

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

A (悪い) 解決策

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

index={i}

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

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

コードの混乱

    Button
  • などの外部ライブラリからすべての要素をラップし、本来このネストを処理することを意図していないコンポーネントを書き直す必要があります...これにより、モジュール性が損なわれ、コードがより複雑になります
  • この組み合わせは良くありません。複数のリストに要素を入れ子にしたい場合は、<MyButtonindex1= { のように、リストの各レベルに新しいインデックスを追加する必要があるため、さらに汚くなります。つまり、ネストされたレベルの数量を確認するには、完全に汎用的な、より複雑なバージョン MyButton
  • を作成する必要があります。
  • index={[index1,index2,index3]} は配列なので、安定した参照がないため、使用できません。 私の知る限り、index には命名規則がありません。つまり、プロジェクト間でコードを共有したり、ライブラリを開発したりすることがより困難になります。
  • もっと良い解決策が見つからないのでしょうか?リストがどこにでもあることを考えると、これに対する適切な解決策がないとは信じられませんが、これに関する文書がいかに少ないかに驚きました。 ######編集### 私はこれをやろうとしています: リーリー
  • そして次のように使用します:
リーリー しかし、まだ完璧ではありません。特に、さまざまなネスト レベルのラッパーが必要であり、新しいプロパティ (

onClick

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

onChange

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

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

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

いいねを押す +0
P粉916760429

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

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

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

リーリー

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

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

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

リーリー

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!