Как оптимизировать повторную визуализацию большого количества дочерних компонентов? - PullRequest
0 голосов
/ 06 марта 2020

Я новичок, когда нужно реагировать. js и я создаю компонент, который содержит большое количество изменяющихся предметов.

TLDR: у меня есть родительский компонент, который содержит много дочерних компонентов (думаю> 1000), которые очень быстро меняют свое состояние. Однако состояние дочерних компонентов должно быть известно в родительском компоненте - поэтому я поднял состояние всех дочерних компонентов до родительского компонента. Поскольку все дочерние компоненты отображаются каждый раз, когда изменяется состояние родительского компонента, производительность довольно низкая. Обновление одного сменного пикселя может занять более 200 мс. Реализация shouldComponentUpdate на дочернем компоненте все еще слишком медленная. У вас есть общий совет, как обращаться с таким случаем?

В качестве конкретного примера c моего вопроса я создал пример "графического редактора" с компонентом PixelGrid, состоящим из 32 на 32 Pixel компоненты:

JS Пример скрипта

Когда для компонента Pixel вызывается событие onMouseDown или onMouseEnter, событие передается родительскому компоненту PixelGrid через обратные вызовы prop, и соответствующее состояние (PixelGrid.state.pixels[i].color) изменяется. Имейте в виду, что компонент PixelGrid должен иметь возможность доступа ко всем значениям пикселей для дальнейшей функциональности, поэтому, я думаю, сохранение состояния в Pixel само по себе на самом деле не вариант. Но это означает, что весь компонент PixelGrid необходимо перерисовать при изменении одного пикселя. Это очевидно очень медленно. Я реализовал shouldComponentUpdate в компоненте Pixel, чтобы немного ускорить процесс, но это все еще не очень быстро, поскольку каждый Pixel проверяется на наличие изменений.

Моя первая реакция состояла в том, чтобы вручную изменить встроенный пиксель CSS в DOM через ссылки React и не сохранять состояние пикселя в this.state.pixels, но в this.pixels, поэтому изменение состояния не вызывает повторного рендеринга, но кажется плохим в обслуживании визуальное представление «вручную».

Итак, как бы вы реализовали такую ​​функциональность с React?

1 Ответ

0 голосов
/ 06 марта 2020

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

Пример (случайное предположение о том, как выглядит ваш Pixel компонент):

const Pixel = React.memo(({x, y, color, ...rest}) => 
  <div style={{
      width: 1, 
      height: 1, 
      x, 
      y, 
      backgroundColor: color
    }}
    {...rest}
  />)

Имейте в виду, что если вы передаете функции в Pixel, их также необходимо запомнить. Например, это неправильно:

const Parent = () => {
  // the callback gets redefined whenever Parent rerenders, causing the React.memo to still update
  return <Pixel onClick={() => {}} />
}

, вместо этого вам нужно будет

const Parent = () => {
  const cb = useCallback(() => {}, []);
  return <Pixel onClick={cb} />
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...