Оптимизация Хранилища Redux Для Более Продуктивных Изменений

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

Внимание.

В этом посте примеры были подготовлены специально для приложений Redux. Но сам подход можно применить и к другим библиотекам.

Совет ниже также работает в реакция-редукция версии 5 .

Мне не удалось добиться желаемого результата в версия 4 .

Я не вникал глубоко в причины.

Итак, стандартный способ хранения ряда элементов в приложении — это сохранение их в массиве:

  
  
  
  
  
   

const state = { targets: [{id: 'target1', radius: 10}, {id: 'target2', radius: 2}] };

Далее, скорее всего, где-то в вашем приложении будет компонент, отображающий этот список:

const TargetsList = connect(state => ({targets: state.targets}))( ({ targets }) => <ul> { targets.map((target) => <TargetView key={target.id} target={target} />) } </ul> );

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

function appReducer(state, action) { if (action.type === 'UPDATE') { return { target: state.target.map((target) => { if (target.id === action.id) { return { .

target, radius: action.radius }; } else { return target; } }) } } // some other code }

Также обновление элемента приведет к обновлению всего представления «TargetsList» (оно будет называться оказывать ).

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

На моей машине обновление одного элемента в списке длиной 1000 занимает примерно 21 мс .

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

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



Как оптимизировать?

Если вы используете github.com/reactjs/react-redux , то вы можете повысить производительность, изменив форму состояния на:

const state = { targetsOrder: ['id-1', 'id-2'], targets: { 'id-1': { id: 'id-1', radius: 10 }, 'id-2': { id: 'id-2', radius: 20 }, } };

Далее вам нужно немного изменить компонент «TargetsList»:

const TargetsList = connect(state => ({targetsOrder: state.targetsOrder}))( ({ targetsOrder }) => <ul> { targetsOrder.map((id) => <TargetView key={id} targetId={id} />) } </ul> );

Обратите внимание, что в этом случае я передаю идентификатор элемента дочернему компоненту, а не весь элемент. Тогда «TargetView» не может быть «тупым компонентом» и должен подписываться на изменения состояния:

const TargetView = connect( (state, ownProps) => ({target: state.targets[ownProps.targetId]}) )(({ target }) => { // your render logic return <Circle radius={target.radius} />; });

Поскольку TargetView подписан на изменения состояния, он будет обновляться при обновлении своих данных.

Важно то, что «TargetList» НЕ БУДЕТ обновляться при изменении элемента в списке, поскольку «targetsOrder» остается прежним.

В некоторых случаях этот метод позволяет значительно повысить производительность.

Обновленное демо с измерениями Теперь обновление одного элемента на моей машине занимает 2,2 мс.

Это почти в 10 раз быстрее, чем в предыдущем примере.

Теги: #JavaScript #react #react.js #react.js #redux #веб-разработка #оптимизация производительности #производительность #производительность #производительность javascript #JavaScript #react.js

Вместе с данным постом часто просматривают: