Оптимизация перерисовок

У нас есть 2 компонента <User /> и <Page />. Мы специально сделали для них два редьюсера, чтобы обновлять их независимо! А у нас? А у нас <User /> каждый раз обновляется при обновлении <Page /> и наоборот.

Добавьте console.log в render метод у <User />:

src/components/User.js

...
render() {
  console.log('<User/> render')
  return <div className="ib user">{this.renderTemplate()}</div>
}
...
user-render-console-log

Перерисовка компонента User происходит постоянно. Это не влияет на производительность нашего мини-приложения, однако, мы не готовы с этим мириться.

Представьте дашборд (панель) с большим количеством виджетов, информация в которых обновляется по событиям от бэкэнда. Если каждый виджет будет перерисовывать полностью весь дашборд, то это будет крайне некрасиво (как для юзера, так и для производительности).

Чтобы такого не было, мы должны каждую отдельную сущность приложения класть в отдельный контейнер.

Будем исправлять, для этого:

  • <App /> становится тупым компонентом, который рендерит 2 контейнера:

    • <PageContainer />

    • <UserContainer />

Данные контейнеры - просто обертки над нашими компонентами, в которых мы "подключаемся (connect) к Redux".

Так же, я сразу заменю название у экшенов внутри mapDispatchToProps: уберу оттуда частичку Action.

В остальном, мы просто "разносим" то, что было в <App /> по раздельным контейнерам.

src/index.js

src/components/App.js

src/containers/PageContainer.js

Как вы могли заметить, все что касалось <Page /> хранится в отдельном контейнере: подписка на часть стора, экшен, пропсы...

То же самое, делаем для <UserContainer />

src/containers/UserContainer.js

Теперь внимание: в компоненте App есть два "независимых компонента". Сейчас при изменении данных в редьюсере для Page - User перерисовываться не будет. App тоже, само собой. App у нас вообще не будет перерисовываться более при таком раскладе.

Снова покликаем по кнопкам (console.log в <User /> остался):

user-not-re-renders-console-log

Еще раз заострю внимание: мы не просто сделали хорошо, мы сделали супер-хорошо! Render - обычно самая дорогая операция. Вызывать "перерисовку" каждого "кусочка" приложения нужно осознанно. Всегда проверяйте (например, так же банально с помощью console.log) сколько раз у вас что рендерится, и нет ли чего лишнего.

Давайте заодно здесь быстренько исправим отрисовку кнопок в <Page />

src/components/Page.js

(Добавьте по вкусу щепотку margin для .btn)

[1] Использовать в данной ситуации index для key плохо?. В данном случае - не плохо. Напоминаю, что индекс в качестве ключа плохо использовать, когда у вас элементы меняются местами. Справедливости ради, здесь в качестве индекса можно было бы использовать "год", так как главное в индексе - это уникальность.

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

Исходный код.

Last updated

Was this helpful?