ReactJS — медленный рендеринг смонтированного компонента -?

Мы столкнулись с медленным рендерингом списков, состоящих из 200+ элементов в проекте на ReactJS (15.1.0) + react-router + redux.

К примеру, есть список пользователей, который представляет собой статические "карточки", т.е. блок с фото, парой ссылок и небольшим текстом. Пользователей много, поэтому при монтировании компонента отображаются первые 30, а остальные по 30 подгружаются c api-сервера по запросу (т.е. по кнопке "показать еще"). Каждая такая карточка это статический компонент, shouldComponentUpdate() которого всегда возвращает false. Компонент списка подписан на обновления через connect() и отрисовывает карточки только если получены новые 30. Пока все хорошо и по мере загрузки данных с бэкенда и отрисовки карточек скорость рендеринга остается стабильной - судя по данным Perf происходит рендеринг только новых 30 экземпляров компонента карточки с общим временем порядка 80-90мс.

Проблема появляется тогда, когда после загрузки относительно небольшого списка (уже от 200-300 карточек) пользователь переходит по ссылке в карточке (компонент Link из react-router), а потом возвращается назад по кнопке браузера.

В этом случае компонент списка заново монтируется и ему приходится перерисовывать сразу все те 200-300 карточек, находящихся в state редакса. При этом скорость рендеринга падает пропорционально кол-ву карточек, т.е. практически в 10 раз, и если на десктопе это терпимо, то для мобильного пользователя время перерисовки страницы составляет 5+ секунд. И это при относительно небольшом кол-ве данных. Кроме того, все приложение (как и, например, redux dev tools в этот момент) "замерзает", т.е. нет возможности как-то отображать, к примеру, индикатор прогресса рендеринга.

Вопрос в следующем - нормальное ли это время рендеринга для реакта при таких условиях? Если да, то какие могут быть способы решения проблемы?
Есть ли возможность каким-либо образом кешировать результаты рендеринга смонтированного ранее компонента? Какие вообще существуют варианты решения проблемы длинных списков, если размер элемента заранее неизвестен?

Спасибо!
  • Вопрос задан
  • 2319 просмотров
Пригласить эксперта
Ответы на вопрос 7
rmaksim
@rmaksim
если в итоге ничего не поможет можно попробовать виртуал-лист или что-то похожее developerdizzle.github.io/react-virtual-list

100К элементов ваще без тормозов
Ответ написан
@vsuhachev
*блок с фото* - это скорее всего и есть проблема тормозов. Если так, то можно подумать в сторону того чтобы инлайнить эти картинки, например.

Ну и самый общий способ - с помощью дизайна UI ограничить видимую область и отображать только те записи которые непосредственно видны на экране. В вашем примере по кнопке "назад" нужно опять сбрасывать состояние компонента таким образом чтобы он отображал 30 записей.

отклик 5 секунд - это ненормально вне зависимости от того react у вас или что-то другое. Приемлемым считается отклик до 1с.
Ответ написан
nuit
@nuit
>нормальное ли это время рендеринга для реакта при таких условиях?

Да. https://localvoid.github.io/uibench/

>Если да, то какие могут быть способы решения проблемы?

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

И в будущем возможно появится возможность инкрементального рендера: https://www.facebook.com/notes/andy-street/react-n...
Ответ написан
Комментировать
Да ну, вроде банальная проблема, которая много где встречается и не решается.
Кэширование, как мне кажется, не вариант. Забьется оперативная память и начнутся тормоза на мобилке.
У меня вк, когда налистаешь стену на несколько сотен постов, очень люто тормозит, даже при переходе на другие страницы - видимо он данные кеширует и спасает только перезагрузка
Ответ написан
Комментировать
profesor08
@profesor08 Куратор тега JavaScript
У вас много картинок. И все эти сотни картинок, заново загружаются. Вот пара вариантов:
1. кешировать картинки.
2. отображать контент, а потом уже подгружать требуемые картинки, по мере неоходимости.
3. грузить миниатюры для мобилок и кешировать их
4. любой другой способ сократить кол-во закгрузок картинок.
Ответ написан
cjey
@cjey
Мой опыт разработки фроненда всего месяц, так что возможно сморожу глупость.
Рискну предположить что тормозит не отрисовка как таковая, а вычисление изменений между VirtualDOM и DOM для внесения изменений.
Мне кажется можно поиграться с параметром key у компонентов карточки, чтобы в одном случае он был постоянным между отрисовками, а во втором случае уникальным, чтобы он считал, что все изменилось и просто выкинул все дерево и добавил новое и сравнить результаты.
Ответ написан
Комментировать
Laiff
@Laiff
Front-end developer
судя по данным Perf происходит рендеринг только новых 30 экземпляров компонента карточки с общим временем порядка 80-90мс

Это не нормальное время для рендринга пачки, вероятнее всего у вас в потоке рендера присутсвуют блокирующие запросы (например синхронное получение каритки) или тяжелые расчеты.
Можно посмотреть на таймлайн этого процесса и разобраться в чем может быть причина.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы