Повышение производительности приложений React и Redux c помощью Reselect


Содержание материала:

React-redux перевыбрать производительность

У меня есть вопрос, касающийся производительности при использовании реселекта в приложении «Реакция редукса»

Библиотека Reselect используется в качестве слоя запоминания для кэширования вычислений, выполненных для повышения производительности, но что, если вам не нужны никакие вычисления / логика?

Является ли более эффективным использование селектора для одного фрагмента данных, или я должен просто использовать вместо этого стандартный метод подключения?

Как уже говорилось, toomuchdesign. Если действительно нет вычислений / логики, и селектор просто возвращает ссылку на объект или значение, которое существует где-то в дереве состояний. Тогда нет необходимости в запомненном селекторе, так как Connect будет выполнять мелкую проверку на равенство.

Поэтому при принятии решения о том, использовать ли простой селектор или использовать createSelector Хороший вопрос, который следует задать: будет ли ссылка на этот объект, массив или функцию, возвращаемую селектором, отличаться при каждом его выполнении?

В результате каждый раз вызывается селектор.

Вернет новый массив, только если массив items изменился.

Поэтому, хотя может показаться заманчивым рассматривать сложность вычисления селекторов в качестве основы для принятия решения, кэширование ссылок является ключевым фактором, обеспечивающим выигрыш в производительности при reselect поскольку это приведет к уменьшению ненужных отрисовок. Так что, хотя запоминание самого селектора может принести выигрыш в производительности. Не забывайте о преимуществах производительности, которые может принести кэширование самой ссылки.

Повышение производительности приложений React и Redux c помощью Reselect

В курсе по React мы немного обсуждали вопросы производительности. Неправильная работа с данными может легко привести к серьёзным просадкам производительности. Об этом нужно помнить и за этим надо следить. Redux нас не просто не избавляет от этого, но и добавляет своих особенностей (хотя кое-какие оптимизации внутри уже встроены).

Для уменьшения количества «холостых» (когда ничего не изменилось) перерисовок виртуального DOM, важно следить за тем, как пишется функция mapStateToProps :

  • Нужно стараться передавать как можно меньше данных (но не меньше, чем нужно).
  • Нужно избегать изменений в mapStateToProps .

Но не забывайте, что сама функция mapStateToProps выполняется всегда, даже если данные не изменились. Это приводит к ненужным и иногда тяжёлым вычислениям.

Последнее рассмотрим подробнее. Напомню наш код из практики:

На первый взгляд в коде всё нормально, но на самом деле Object.values создаёт каждый раз новый объект, даже если tasks остались прежними. А значит ни о какой эффективности не может быть и речи. Очевидным решением будет перенести эту логику внутрь компонента, но тогда теряется одно из главных преимуществ маппинга. Компоненты завязываются на структуру состояния и выполняют работу по подготовке данных, которая, кстати, начнёт дублироваться.

Для решения этой задачи создан пакет reselect . Он позволяет создавать специальные функции «селекторы», которые выполняют мемоизацию результата. То есть если данные не поменялись, то и результат работы функции будет тем же самым значением или объектом в случае составных данных.

Отмечу, что reselect не связан ни с Redux, ни с React. Нет никакого слоя интеграции. Селекторы сами по себе и их легко использовать в контейнерах без конфигурации.

Перед тем как создать первый селектор, нужно написать функцию, которая принимает на вход состояние и возвращает нужный срез данных. В нашем случае используется функция getTasks . Затем с помощью функции createSelector создаётся селектор. В примере выше в функцию createSelector передаётся наша исходная функция и вторая функция, которая производит фильтрацию данных, полученных первой функцией.

Повышение производительности приложений React и Redux c помощью Reselect

1109 просмотра

2 ответа

266 Репутация автора

У меня есть вопрос, касающийся производительности при использовании повторного выбора в приложении «Реакция на редукцию».

Библиотека Reselect используется в качестве слоя напоминания для кэширования вычислений, выполненных для повышения производительности, но что если вам не нужны какие-либо вычисления / логика?

Является ли более эффективным использование селектора для одного фрагмента данных, или я должен просто использовать вместо этого стандартный метод соединения?

Ответы (2)

-1 плюса

3707 Репутация автора

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

Затем подключите ваши селекторы к вашим компонентам через Redux connect .

Не используйте, reselect если вам не нужны суперспособности кеширования / запоминания!

6 плюса

1345 Репутация автора

Как уже говорилось, toomuchdesign. Если действительно нет вычислений / логики, и селектор просто возвращает ссылку на объект или значение, которое существует где-то в дереве состояний. Тогда нет необходимости в запомненном селекторе, так как мелкая проверка на равенство будет выполняться connect .

Следовательно, при принятии решения о том, использовать ли простой селектор или использовать createSelector хороший вопрос, который нужно задать, будет: будет ли ссылка на этот объект, массив или функцию, возвращаемую селектором, отличаться при каждом его выполнении?

В результате каждый раз вызывается селектор.

Вернет только новый массив, если items массив изменился.

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

3.5 Оптимизация производительности

Внутри React использует несколько умных подходов, чтобы минимизировать количество дорогостоящих операций DOM, необходимых для обновления пользовательского интерфейса. Для многих приложений использование React приведет к созданию быстрого пользовательского интерфейса, не выполняя много работы, чтобы специально оптимизировать производительность. Тем не менее, есть несколько способов ускорить ваше приложение React.

3.5.1 Использование сборки Production

Если вы проводите бенчмаркинг или испытываете проблемы с производительностью в своих приложениях React, убедитесь, что вы работаете с минифицированной production-сборкой.

По умолчанию React содержит много полезных предупреждений. Эти предупреждения очень полезны в разработке. Тем не менее, они делают React-приложение больше и медленнее, поэтому вы должны использовать production-версию при развертывании приложения.

Если вы не уверены, правильно ли настроен процесс сборки, вы можете проверить это, установив React Developer Tools для Chrome. Если вы заходите на сайт с React в режиме production, значок будет иметь темный фон:

Если вы заходите на сайт с React в режиме разработки, значок будет иметь красный фон:

Ожидается, что вы используете режим development при работе с вашим приложением и режим production при развертывании приложения для пользователей.

Ниже вы можете найти инструкции по созданию своего приложения для production.

3.5.2 Создание приложения React

Если ваш проект построен с помощью приложения Create React , запустите:

Это создаст production-сборку вашего приложения в папке build/ вашего проекта.

Помните, что это необходимо только перед развертыванием в production. Для нормальной разработки используйте npm start.

3.5.3 Однофайловые сборки

Предлагаются готовые версии React и React DOM в виде отдельных файлов:

Помните, что только файлы React, заканчивающиеся на .production.min.js , подходят для production.

3.5.4 Бранч (Brunch)

Для самой эффективной production-сборки бранча установите плагин uglify-js-brunch:

Затем, чтобы создать production-сборку, добавьте флаг -p в команду сборки:

Помните, что вам нужно сделать это только для production сборок. Вы не должны передавать флаг -p или применять этот плагин в разработке, потому что он скроет полезные предупреждения React и сделает сборки намного медленнее.

3.5.5 Browserify

Для наиболее эффективной сборки сборки Browserify установите несколько плагинов:


Чтобы создать production-сборку, убедитесь, что вы добавили эти преобразования (порядок имеет значение):

  • Преобразование envify обеспечивает правильную среду сборки. Сделайте его глобальным ( -g ).
  • Преобразование uglifyify устраняет импорты, добавленные на стадии разработки. Сделайте его глобальным ( -g ).
  • Наконец, результирующая связка передается по каналу в uglify-js для минификации.

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

3.5.6 Rollup

Для наиболее эффективной production-сборки Rollup установите несколько плагинов:

Чтобы создать сборку, убедитесь, что вы добавляете эти плагины (порядок имеет значение):

  • Плагин replace обеспечивает правильную среду сборки.
  • Плагин commonjs обеспечивает поддержку CommonJS в Rollup.
  • Плагин uglify сжимает и управляет финальной связкой (бандлом).
Топ-пост этого месяца:  Центрирование с помощью Sass

Полный пример установки смотреть здесь .

Помните, что вам нужно сделать это только для production сборок. Вы не должны применять плагин uglify или плагин replace со значением «production» в разработке, потому что они будут скрывать полезные предупреждения React и делать сборки намного медленнее.

3.5.7 webpack

Для создания наиболее эффективной webpack production сборки обязательно включите эти плагины в свою production конфигурацию:

Об этом вы можете узнать в документации по webpack .

Помните, что вам нужно только сделать это для production сборок. Вы не должны применять UglifyJsPlugin или DefinePlugin со значением ‘production‘ в разработке, потому что они будут скрывать полезные предупреждения React и делать сборки намного медленнее.

3.5.8 Профилирование компонентов с помощью вкладки «Производительность Chrome»

В режиме development вы можете визуализировать, как компоненты монтируются, обновляются и демонтируются, используя инструменты производительности в поддерживаемых браузерах. Например:

Чтобы сделать это в Chrome:

  • Временно отключите все расширения Chrome, особенно React DevTools. Они могут значительно исказить результаты!
  • Убедитесь, что вы запускаете приложение в режиме разработки.
  • Загрузите ваше приложение с помощью ?react_perf в строке запроса (например, http://localhost:3000/?react_perf ).
  • Откройте вкладку «Performance» в Chrome DevTools и нажмите «Record».
  • Выполните действия, которые вы хотите профилировать. Не записывайте более 20 секунд или Chrome будет зависать.
  • Остановите запись.
  • События React будут сгруппированы под меткой User Timing.

Обратите внимание, что цифры относительны, поэтому компоненты будут быстрее отрисовываться в production. Тем не менее, это должно помочь вам понять, когда не связанный пользовательский интерфейс обновляется по ошибке, а также насколько глубоко и насколько часто обновляются ваши пользовательские интерфейсы.

В настоящее время Chrome, Edge и IE являются единственными браузерами, поддерживающими эту функцию, но можно использовать стандартный User Timing API .

3.5.9 Профилирование компонентов с помощью профайлера DevTools

react-dom 16.5+ и react-native 0.57+ предоставляют расширенные возможности профилирования в режиме DEV с помощью React DevTools профайлера. Обзор профайлера можно найти в главе обновлений. Видео-пошаговое руководство по профайлеру также доступно на YouTube .

Если вы еще не установили React DevTools, вы можете найти его здесь:

Профайлинг продакшен бандла для react-dom также доступен как react-dom/profiling . Подробнее о том, как использовать этот пакет, читайте на сайте fb.me/react-profiling.

3.5.10 Виртуализация длинных списков

Если ваше приложение отображает длинные списки данных (сотни или тысячи строк), мы рекомендуем использовать метод, известный как «экранирование». Этот метод отрисовывает только небольшое подмножество ваших строк в данный момент времени и может значительно сократить время, необходимое для повторной переотрисовки компонентов, а также количество создаваемых узлов DOM.

react-window и react-virtualized — популярные библиотека для экранирования. Они предоставляют различные повторно используемые компоненты для отображения списков, гридов и табличных данных. Вы также можете создать свой собственный экранирующий компонент, как это сделано в Twitter, если желаете что-то более специфическое для вашего конкретного случая.

3.5.11 Избежание согласования

React строит и поддерживает внутреннее представление отображаемого пользовательского интерфейса. Оно включает элементы React, которые вы возвращаете из своих компонентов. Это представление позволяет React избегать создания узлов DOM и доступа к существующим узлам без необходимости, поскольку это может быть гораздо медленнее, чем те же операции над простыми объектами JavaScript. Иногда его называют «виртуальным DOM», и оно работает аналогично в React Native.

Когда свойства или состояние компонента изменяются, React решает, требуется ли фактическое обновление DOM, сравнивая вновь возвращенный элемент с ранее отображаемым. Когда они не равны, React обновит DOM.

Вы можете визуализировать эти перерисовки виртуального DOM с помощью React DevTools:

В консоли разработчика выберите параметр « Highlight Updates » на вкладке « React »:

Взаимодействуя со своей страницей, вы должны увидеть, что вокруг любых компонентов, которые были переотрисованы, мгновенно появляются цветные границы. Это позволяет вам выявлять повторные отрисовки, которые не были необходимыми. Вы можете узнать больше о функции React DevTools из этого поста в блоге от Ben Edelstein .

Рассмотрим этот пример:

Обратите внимание, что когда мы вводим второе todo, первое todo также мигает на экране при каждом нажатии клавиши. Это означает, что он повторно отрисовывается React-ом вместе с элементом input. Это иногда называют «напрасной/бесполезной» отрисовкой. То есть мы знаем, что повторная отрисовка необязательна, так как контент первого todo не изменился. Но React об этом не знает, из-за чего и возникает такой эффект.

Несмотря на то, что React обновляет только измененные узлы DOM, переотрисовка все же занимает некоторое время. Во многих случаях это не вызывает проблем, но если замедление заметно, вы можете все это ускорить, переопределив метод жизненного цикла shouldComponentUpdate() , который запускается до начала процесса повторной отрисовки. Реализация этой функции по умолчанию возвращает true , указывая React выполнить обновление:

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

В большинстве случаев вместо записи shouldComponentUpdate() вручную вы можете наследоваться от React.PureComponent . Это эквивалентно реализации shouldComponentUpdate() с неглубоким сравнением текущих и предыдущих props и state .

3.5.12 shouldComponentUpdate в действии

Вот поддерево компонентов. Для каждого из них SCU указывает, что возвратил shouldComponentUpdate , а vDOMEq указывает, эквивалентны ли отображаемые элементы React. Наконец, цвет круга указывает, должен ли компонент быть согласован или нет.

Так как shouldComponentUpdate возвратил false для поддерева с корнем C2 , React не попытался отрисовать C2 , и, следовательно, даже не нужно было вызывать shouldComponentUpdate на C4 и C5 .

Для C1 и C3 shouldComponentUpdate вернул true , поэтому React пришлось спуститься к листьям и проверить их. Для C6 shouldComponentUpdate вернул true , и поскольку отображаемые элементы не были эквивалентны, React должен был обновить DOM.

Последний интересный случай — C8 . React должен был отобразить этот компонент, но поскольку возвращаемые им элементы React были равны ранее предоставленным, ему не нужно было обновлять DOM.

Обратите внимание, что React должен был делать DOM-изменения только для C6 , что было неизбежно. Для C8 этого удалось избежать сравнением отрисовываемых элементов React, а для поддеревьев C2 и C7 , даже не пришлось сравнивать элементы, так как нас выручил shouldComponentUpdate и отрисовка не вызвалась.

3.5.13 Примеры

Если единственный способ изменения вашего компонента – когда переменная props.style или state.value изменяется, вы могли бы выполнить проверку в shouldComponentUpdate как:

В этом коде shouldComponentUpdate просто проверяет, есть ли какие-либо изменения в props.style или state.value . Если эти значения не изменяются, компонент не обновляется. Если ваш компонент стал более сложным, вы можете использовать аналогичную схему «поверхностного сравнения» между всеми полями props и state , чтобы определить, должен ли компонент обновляться.

Этот шаблон настолько распространен, так что React предоставляет помощника для использования данной логики — просто наследуйтесь от React.PureComponent . Таким образом, следующий код — более простой способ добиться того же эффекта:

В большинстве случаев вы можете использовать React.PureComponent вместо написания собственного shouldComponentUpdate . Он делает только неглубокое сравнение, поэтому вы не можете использовать его, если props или state могут быть изменены таким образом, что нечеткое сравнение будет пропущено.

Это может быть проблемой для более сложных структур данных. Предположим, что вы хотите, чтобы компонент UserList отображал список пользователей, разделенных запятыми, с родительским компонентом UserAdmin , который позволяет вам щелкнуть кнопку, чтобы добавить очередного пользователя в список. Этот код работает неправильно:

Проблема в том, что PureComponent выполнит простое сравнение старых и новых значений this.props.users . Поскольку этот код изменяет массив слов в методе onAddUser компонента UserAdmin , старые и новые значения this.props.users при сравнении будут одинаковы, даже если фактические пользователи в массиве изменились. Массив, а следовательно и ссылка на него остались теми же. Таким образом, UserList не будет обновляться, даже если он содержит новых пользователей, которые должны быть отображены.

3.5.14 Мощь неизменяющихся данных

Самый простой способ избежать этой проблемы — избежать изменения значений, которые вы используете в качестве props или state . Например, описанный выше метод onAddUser можно переписать с помощью concat вот так:

ES6 поддерживает spread синтаксис для массивов, который может сделать это проще. Если вы используете приложение Create React App , этот синтаксис доступен по умолчанию.

Вы также можете переписать код, который изменяет объекты, чтобы избежать изменения, аналогичным образом. Предположим, что у нас есть объект с именем user , и мы хотим написать функцию, которая устанавливает user.email в передаваемое значение. Мы могли бы написать:

Чтобы написать это без изменения исходного объекта, мы можем использовать метод Object.assign :

updateUserEmail теперь возвращает новый объект, а не изменяет старый. Object.assign входит в ES6 и требует полифила.

JavaScript предоставляет spread оператор для добавления свойств объекта, чтобы упростить его обновление без изменения:

Если вы используете приложение Create React, по умолчанию доступны как Object.assign , так и синтаксис spread для объектов.


3.5.15 Использование неизменяемых структур данных

Immutable.js — еще один способ решить эту проблему. Он предоставляет неизменные, постоянные коллекции, которые работают через совместное использование структуры:

  • Неизменяемость: после создания коллекция не может быть изменена в любой другой момент времени.
  • Постоянство: новые коллекции могут быть созданы из предыдущей коллекции и изменения, такого как set . Оригинальная коллекция по-прежнему действительна после создания новой коллекции.
  • Совместное использование структуры: новые коллекции создаются с использованием такой же структуры, как и исходная коллекция, что позволяет сократить количество копий до минимума для повышения производительности.
Топ-пост этого месяца:  React JS Material UI

Неизменность делает отслеживание изменений дешевым. Изменение всегда приведет к созданию нового объекта, поэтому нам нужно только проверить, изменилась ли ссылка на объект. Например, в этом обычном JavaScript-коде:

Несмотря на то, что b был отредактирован, поскольку это ссылка на тот же объект, что и a , это сравнение возвращает true . Вы можете написать аналогичный код с immutable.js:

В этом случае, поскольку при изменении a возвращается новая ссылка, мы можем с уверенностью сказать, что a изменился.

Есть две другие библиотеки, которые могут помочь использовать неизменяемые данные: seamless-immutable и immutability-helper .

Неизменяемые структуры данных предоставляют вам дешевый способ отслеживания изменений объектов, и все, что вам нужно для реализации shouldComponentUpdate . Это может дать вам хороший прирост производительности.

React-redux reselect performance

У меня есть вопрос относительно производительности при повторном выборе в приложении реакции редукции.

Библиотека Reselect используется как уровень memoization для кэширования вычислений, которые сделаны для производительности, но что делать, если вам не нужны какие-либо вычисления/логика?

Лучше ли использовать селектор для одиночной части данных или использовать вместо этого стандартный метод подключения?

Создан 03 май. 17 2020-05-03 22:41:09 Alexg2195

У вас действительно есть проблемы с производительностью? Если нет, не тратьте время на такие вещи. – Sulthan 06 май. 17 2020-05-06 11:47:16

Более того, смотря на это с точки зрения простоты и обслуживания. Как и в написании дополнительного кода для селекторов, которые просто получают единую государственную информацию? Помогает ли кэширование в этой ситуации. – Alexg2195 07 май. 17 2020-05-07 17:39:17

2 ответа

Как указано выше. Если в действительности нет вычислений/логики, а селектор просто возвращает ссылку на объект или на значение, которое существует где-то в дереве состояний. Тогда нет необходимости в memoized селекторе, так как проверка неглубокой проверки будет сделана connect .

Поэтому при принятии решения о том, следует ли использовать простой селектор или использовать createSelector Хороший вопрос, который задает вопрос: будет ли ссылка на этот объект, массив или функция, возвращаемая селектором, различной при каждом ее выполнении?

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

Принимая во внимание:

бы вернуть только новый массив, если items массив изменился.

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

Создан 22 июн. 17 2020-06-22 08:26:39 Chad Edrupt

Creating Sortable List with React, Redux, and Reselect

The Internet is full of examples and solutions implementation of sorting in the collection, but as it often happens, the found ready-made solution does not entirely fit, as each developer tries to solve their specific problem. So at the end of the day, you may stop searching and write everything yourself, eventually getting not only the working code but also gaining over 9000 experience to self-confidence.

Here is my solution for this task, I implemented on one of our projects. This article is unlikely to be interesting for those who are already a dab hand at React and its ecosystem. It’s for those who have been familiar with it for a while and, just like me, once been looking for similar articles.

First I’ll write a simple component and then bring the logic outside. As I need, not only the component itself to know about the state of sorting but also any other component connected to the project.

So, let’s get started.

Writing a simple component

Let’s create a simple React App and render the table with some data.

Let’s add the ability to sort the list by any of the fields, for example, by First Name.

To do this, in the internal state of the App component, we define the collection for rendering and the sorting parameters; add a handler function that would change this collection. We will sort by clicking on the header of the First Name column.

I use the orderBy function because inside the project we widely use lodash, and it is just more convenient here than the native implementation.

Then we can complicate it and make a general sorting function by bringing in the field by which we want to sort:

Now our component is able to sort the collection in almost any field.

At the moment we don’t pay much attention to the field type and sort by it as if it were a string or a number. But there is a date in our collection. And sorting by such a field will not work correctly since the data in the object is represented by a string. But, we will solve this “problem” a bit later ��.

Adding Redux and Reselect, made an App more complex

Our component perfectly solves the task. But, what if some other part of our App needs to be aware of how our list is now sorted? For example, you need to show outside the list component that it is sorted — to render some marker or icon, or you generally sort your list on the server, and then you need to transfer the sorting parameters to it. And here, obviously, we require that the state in which the parameters are stored to be external.

To do this, we add Redux to our App and put our collection in the initialState of the future store.

Let’s describe reducers:

Now let’s add actions:

In orderByType, we can transfer not only the key by which the collection will be sorted but also the data type, to clarify exactly how it will be sorted.

So finally the code of the main component has turned into:

Now clicking on the table headers, we write the sorting parameters into redux state. And we can get them from any component subscribed to the state (precisely what we did in our component).

But now no sorting happens, because the component is transferred as props

and it still doesn’t depend on parameters changing in the state. Let’s fix it.

We could leave the handleColumnHeaderClick function inside the main component and sort the collection in the same place. But we want our component to know nothing about which collection and how it renders.

Using library reselect, we will write a selector for our collection

And we’ll subscribe our component to state using a selector:

Along with the selector, we wrote one helper function – orderByType. We can set how exactly the collection will be sorted via this function. For example, above, in setSortParams for the hiringAt field, we passed the date type as the second argument. And during the sorting, instead of a string in the “mm/dd/yyyy” format, we cast the date values to Date type and thereby solve the sorting mentioned above by date problem.

In orderByType we also may add a case with a float or number type:

This can be useful if the data in the collection does not match its type. For example, the age or amount of salary is given as a string. And then setting

the data will be cast to the correct type.

That’s it! Now the component is subscribed to the state, where the collection comes from, but already rendered by the parameter-aware selector function. The only thing that remains inside the component is the action call with the transfer of a key and possibly a type to it.

What We’ve Done?

We’ve turned the App component out of the complex, and in the long run hard to expand and hard to maintain into an almost “clean” one and brought out all the logic that implements the sorting into its proper place:

The code in action is responsible for handling the click on the appropriate header and calling the reducer

Reducer puts data into a global state

Selector code is in charge of selecting data from the state and their sorting, depending on the parameters that came from the reducer

Топ-пост этого месяца:  SEO словарь популярных терминов, сокращений и сленга вебмастеров

In this case, it is possible to change the behavior of the sorting function or the selector as much as you want — the component that renders the collection doesn’t need to be changed at all.


Source Code

All source code is available on CodeSandbox with additional options.

Игра в жизнь в React / Redux, помощь в повышении производительности

Я работаю на версию игры жизни в среагировать / Redux / JavaScript, в то время как у меня есть это работает производительность ужасно.

На данный момент я нахожусь на каждом тике (250,500,750ms изменяемый пользователем) обновление состояния каждой ячейки. Для этого я перекручивание через массив объектов, представляющих каждую клетку. Внутри каждого объекта является параметр, называемый статус, который может быть целым числом от 1 для живой или 0 для мертвых.

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

Затем я запускаю это число через если / то поток решить новое состояние этой ячейки.

Этот процесс затем повторяется для каждой ячейки в приложении. Как только это будет сделано новое состояние каждой ячейки отправляется с помощью Redux и обновления компонентов по мере необходимости.

В реальной точке зрения, каждая ячейка представляет собой компонент, который реагирует получает это состояние в качестве опоры из контейнера, который является сеткой. У меня есть настройки shoulComponentRender () только повторная визуализация ячейки, когда это изменение статуса жизни.

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

Любая помощь / помощь оценили!

Я думаю, что это может быть проблемой. По профилированию мы видим:

У вас есть всплески работы с регулярными интервалами, каждый из которых принимает около 85ms , которая является очень ненормальной. Глядя вниз колл-стек есть triggerTimer и последующие startTimer вызовы функций.

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

React-redux reselect performance

У меня есть вопрос относительно производительности при повторном выборе в приложении реакции редукции.

Библиотека Reselect используется как уровень memoization для кэширования вычислений, которые сделаны для производительности, но что делать, если вам не нужны какие-либо вычисления/логика?

Лучше ли использовать селектор для одиночной части данных или использовать вместо этого стандартный метод подключения?

Создан 03 май. 17 2020-05-03 22:41:09 Alexg2195

У вас действительно есть проблемы с производительностью? Если нет, не тратьте время на такие вещи. – Sulthan 06 май. 17 2020-05-06 11:47:16

Более того, смотря на это с точки зрения простоты и обслуживания. Как и в написании дополнительного кода для селекторов, которые просто получают единую государственную информацию? Помогает ли кэширование в этой ситуации. – Alexg2195 07 май. 17 2020-05-07 17:39:17

2 ответа

Как указано выше. Если в действительности нет вычислений/логики, а селектор просто возвращает ссылку на объект или на значение, которое существует где-то в дереве состояний. Тогда нет необходимости в memoized селекторе, так как проверка неглубокой проверки будет сделана connect .

Поэтому при принятии решения о том, следует ли использовать простой селектор или использовать createSelector Хороший вопрос, который задает вопрос: будет ли ссылка на этот объект, массив или функция, возвращаемая селектором, различной при каждом ее выполнении?

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

Принимая во внимание:

бы вернуть только новый массив, если items массив изменился.

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

Создан 22 июн. 17 2020-06-22 08:26:39 Chad Edrupt

Игра в жизнь в React / Redux, помощь в повышении производительности

Я работаю на версию игры жизни в среагировать / Redux / JavaScript, в то время как у меня есть это работает производительность ужасно.

На данный момент я нахожусь на каждом тике (250,500,750ms изменяемый пользователем) обновление состояния каждой ячейки. Для этого я перекручивание через массив объектов, представляющих каждую клетку. Внутри каждого объекта является параметр, называемый статус, который может быть целым числом от 1 для живой или 0 для мертвых.

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

Затем я запускаю это число через если / то поток решить новое состояние этой ячейки.

Этот процесс затем повторяется для каждой ячейки в приложении. Как только это будет сделано новое состояние каждой ячейки отправляется с помощью Redux и обновления компонентов по мере необходимости.

В реальной точке зрения, каждая ячейка представляет собой компонент, который реагирует получает это состояние в качестве опоры из контейнера, который является сеткой. У меня есть настройки shoulComponentRender () только повторная визуализация ячейки, когда это изменение статуса жизни.

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

Любая помощь / помощь оценили!

Я думаю, что это может быть проблемой. По профилированию мы видим:

У вас есть всплески работы с регулярными интервалами, каждый из которых принимает около 85ms , которая является очень ненормальной. Глядя вниз колл-стек есть triggerTimer и последующие startTimer вызовы функций.

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

Проблемы производительности с древовидной структурой и shouldComponentUpdate в React/Redux — reactjs

Я новичок в React, Redux и ImmutableJS и столкнулся с некоторыми проблемами производительности.

У меня есть большая древовидная структура данных, которую я сейчас храню в виде плоского списка в этой структуре:

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

Я хочу использовать shouldComponentUpdate , чтобы при обновлении node 3 узлы 2 и 4 не обновлялись. Это было бы легко, если бы данные были сохранены как дерево (я мог бы просто проверить, есть ли this.props !== nextProps ), но поскольку данные хранятся в плоском списке, проверка будет значительно сложнее.

Как мне хранить данные и использовать shouldComponentUpdate (или другие методы) для поддержки гладкого интерфейса с сотнями или тысячами узлов дерева?

Edit

Я подключил хранилище на верхнем уровне, а затем должен передать весь хранилище до подкомпонентов.

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

Похоже, что лучшим решением (спасибо @Dan Abramov) было бы подключение каждого , а просто подключение на верхнем уровне. Я проведу это сегодня вечером.

    1 2
  • 8 окт 2020 2020-10-08 19:50:14
  • Paddy Mann

2 ответа

Решение Дэн Абрамова в 99% случаев обычно прекращается.

Но время вычисления, требуемое для каждого приращения, пропорционально O (n) количеству узлов в дереве, поскольку каждый подключенный node HOC должен выполнить немного кода (например, сопоставление идентичности. ). Однако этот код довольно быстро выполняется.

Если вы протестируете решение Дэн Абрамов, с 10k узлами на моем ноутбуке, я начинаю видеть некоторую задержку при попытке увеличить счетчик (например, задержка в 100 мс). Вероятно, это намного хуже на дешевых мобильных устройствах.

Можно утверждать, что вы не должны пытаться отображать 10 000 элементов в DOM сразу, и я полностью согласен с этим, но если вы действительно хотите отображать множество элементов и подключать их, это не так просто.

Если вы хотите повернуть этот O (n) в O (1), вы можете реализовать свою собственную систему connect , где HOC (компонент более высокого порядка ) подписка активируется только при обновлении базового счетчика вместо всех подписчиков HOC.

Я рассказал, как это сделать в этом .

Я создал issue для реакции-сокращения, чтобы connect стал более гибким и позволял легко настраивать подписку на магазин через опции. Идея состоит в том, что вы должны иметь возможность повторно использовать код connect и эффективно подписываться на изменения срезов штата вместо глобальных изменений состояния (т.е. store.subscribe() ).

По-прежнему ваша собственная ответственность создать энхансер магазина с помощью метода subscribeNode .

Добавить комментарий