Реагировать перехватом useCallback для рендеринга карты

При передаче обратного вызова компоненту, я должен использовать 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? Вышеуказанный правильный способ передать несколько обратных вызовов? Это действительно работает и знает, чтобы запоминать каждый обратный вызов в соответствии с элементом массива?

3 ответа

Решение

Преобразуйте возвращенный сопоставленный JSX в компонент, и тогда вы сможете без проблем использовать Обратный вызов

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} />
  });
};

Теперь это прямо не рекомендуется в документации.https://reactjs.org/docs/hooks-rules.html

Старый ответ

Ответ на повторный архитектор - уклонение от вопроса ИМО. Хотя я думаю, что создание нового компонента, вероятно, хорошая идея.

Чтобы ответить на вопрос, ваш код:

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 и все, что они делают, чтобы уменьшить массив до некоего ключа для мемоизированной функции.

Если вы не работаете над некоторыми с ТОННОЙ элементов, EG реагирует на виртуальные компоненты с неограниченной прокруткой, вы действительно можете безопасно использовать Callback таким, какой вы есть. Фактически, небольшие накладные расходы на память, вероятно, намного дешевле, чем повторный рендеринг всех этих компонентов.

Еще одна альтернатива:

      import doSomething from "./doSomething";

const FrequentlyRerendersMap = ({ ids }) => {
  const onEvent = useCallback((id) => () => doSomething(id), []);

  return ids.map(id => {
    
    return (
      <ExpensiveComponent key={id} onEvent={ onEvent: onEvent(id) } />
    );
  });
};
Другие вопросы по тегам