12

コールバックをコンポーネントに渡すときは、useCallbackフックを使用してメモ化されたコールバックを返す必要があります (不要なレンダリングを防ぐため):

import doSomething from "./doSomething";
const FrequentlyRerenders = ({ id }) => {
  const onEvent = useCallback(() => doSomething(id), [id]);
  return (
    <ExpensiveComponent onEvent={ onEvent } />
  );
};

しかし、マップを使用している場合はどうなりますか? 例えば:

import doSomething from "./doSomething";
const FrequentlyRerendersMap = ({ ids }) => {
  return ids.map(id => {
    const onEvent = useCallback(() => doSomething(id), [id]);
    return (
      <ExpensiveComponent key={id} onEvent={ onEvent } />
    );
  });
};

を適切に使用するにはどうすればよいuseCallbackですか? 上記は複数のコールバックを渡す正しい方法ですか? 配列の項目に従ってすべてのコールバックを memioze することは本当に機能し、知っていますか?

4

3 に答える 3

12

返されたマップされた JSX をコンポーネントに変換すると、Callback を問題なく使用できます

import doSomething from "./doSomething";
const MappedComponent =(props) => {
   const onEvent = useCallback(() => doSomething(props.id), []);
   return (
      <ExpensiveComponent onEvent={ onEvent } />
   );
}

const FrequentlyRerendersMap = ({ ids }) => {
  return ids.map(id => {
    return <MappedComponent key={id} id={id} />
  });
};
于 2019-05-03T05:55:45.617 に答える
-2

これは現在、ドキュメントで明示的に推奨されていません。 https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

古い答え

再構築への答えは、質問 IMO を回避することです。ただし、新しいコンポーネントを作成することはおそらく良い考えだと思います。

ただし、質問に答えるために、コードは次のとおりです。

import doSomething from "./doSomething";
const FrequentlyRerendersMap = ({ ids }) => {
  return ids.map(id => {
    const onEvent = useCallback(() => doSomething(id), [id]);
    return (
      <ExpensiveComponent key={id} onEvent={ onEvent } />
    );
  });
};

マップでメモするために実際にやりたいことです。useCallback の実装はわかりませんが、メモリ オーバーヘッドはほとんど追加されないはずです。stackFrame、および配列をメモ化された関数の何らかのキーに縮小するために行うこと。

多数の要素を使用していくつかの作業を行っていない限り、たとえば仮想化されたコンポーネントの無制限のスクロールに反応する場合を除き、Callback をそのまま使用しても現実的に安全です。実際、わずかなメモリ オーバーヘッドは、これらすべてのコンポーネントを再レンダリングするよりもおそらくはるかに安価です。

于 2019-06-24T22:42:02.300 に答える