React.useMemo не работает для предотвращения повторного рендеринга - PullRequest
1 голос
/ 22 октября 2019

У меня есть следующий простой компонент:

const Dashboard = () => {
  const [{ data, loading, hasError, errors }] = useApiCall(true)

  if (hasError) {
    return null
  }

  return (
    <Fragment>
      <ActivityFeedTitle>
      <ActivityFeed data={data} isLoading={loading} />
    </Fragment>
  )
}

export default Dashboard

Я бы хотел запретить ВСЕ повторные рендеринг компонента ActivityFeedTitle, чтобы он отображался только один раз при загрузке. Насколько я понимаю, я должен иметь возможность использовать хук React.useMemo с пустым массивом зависимостей для достижения этой цели. Я изменил на return на:

return (
    <Fragment>
        {React.useMemo(() => <ActivityFeedTitle>, [])}
        <ActivityFeed data={data} isLoading={loading} />
    </Fragment>
)

Насколько мне известно, это должно предотвратить все повторные рендеры этого компонента? Тем не менее, компонент ActivityFeedTitle по-прежнему отображается повторно при каждом отображении компонента Dashboard.

Чего мне не хватает?

РЕДАКТИРОВАТЬ:

Использование React.memo все еще вызывает ту же проблему. Я попытался запоминать свой ActivityFeedTitle компонент следующим образом:

const Memo = React.memo(() => (
  <ActivityFeedTitle />
))

, а затем использовал его в своем возвращении:

return (
    <Fragment>
        {<Memo />}
        <ActivityFeed data={data} isLoading={loading} />
    </Fragment>
)

Та же проблема возникает. Я также попытался передать () => false следующее как второй аргумент React.memo, но это также не сработало.

Ответы [ 4 ]

1 голос
/ 22 октября 2019

Используйте React.memo() вместо того, чтобы запоминать компоненты на основе реквизита.

React.memo(function ActivityFeedTitle(props) {
  return <span>{props.title}</span>
})

Обратите внимание:

Этот метод существует только как оптимизация производительности . Не полагайтесь на него, чтобы «предотвратить» рендеринг, так как это может привести к ошибкам.

0 голосов
/ 22 октября 2019

Вы можете использовать React.memo и использовать его там, где вы определяете свой компонент, а не там, где вы создаете экземпляр компонента. Вы можете сделать это в вашем компоненте ActivityFeedTitle как

const ActivityFeedTitle = React.memo(() => {
  return (
   //your return
  )
})

Надеюсь, это поможет

0 голосов
/ 22 октября 2019

Вы используете React.memo неправильно. React.memo принимает компонент в качестве аргумента.

const Memo = React.memo(ActivityFeedTitle />);

Я бы порекомендовал вам переместить ваше состояние, то есть data и isLoading в компонент ActivityFeed, чтобы ваш компонент Dashboard не рендерился повторно и вам не нужно было переноситьваш компонент заголовка в заметке.

0 голосов
/ 22 октября 2019

Вы неправильно используете useMemo.

Из перехватчиков реагирования doc:

Передайте функцию «create» и массив зависимостей. useMemo будет повторно вычислять запомненное значение только тогда, когда одна из зависимостей изменилась. Эта оптимизация помогает избежать дорогостоящих вычислений при каждом рендеринге.

Если массив не указан, новое значение будет вычисляться при каждом рендеринге.

Вам необходимо использовать useMemo напримерuseEffect здесь для вычисления значения, а не для рендеринга компонента.

React.memo

React.memo() - это то, что вы ищете. Это предотвращает повторный рендеринг, если реквизит не меняется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...