Как избежать бесполезного mapStateToProps()?

Предположим, что приложение React + Redux имеет страницу, содержащую ~100 флажков MUI.

Все они контролируются с помощью состояния Redux, например:

let CheckboxComponent = React.createClass({

  shouldComponentUpdate(nextProps) {
    return nextProps.activeList !== this.props.activeList;
  }

  render() {

    let isChecked = this.props.activeList.indexOf(this.props.myId) >= 0;

    return <Checkbox
      checked={isChecked}
    />;
  }

});

function mapStateToProps(state) {
  return {
    activeList: state.form.myForm.values.activeList;
  };
}

CheckboxComponent = connect(mapStateToProps)(CheckboxComponent);

Теперь скажем, что у меня также есть контролируемый <input> на той же странице, используя тот же магазин Redux. Каждое нажатие клавиши на входе вызывает изменение состояния Redux. Таким образом, при вводе это вызовет много изменений, но не для activeList,

Меня беспокоит то, что - если я не ошибаюсь - mapStateToProps и, как следствие, shouldComponentUpdate каждого <CheckboxComponent> вызывается при каждом нажатии клавиши - это несколько сотен бесполезных вызовов функций.

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

Все это можно решить, если mapStateToProps() не будет вызываться для изменений состояния Redux, которые не связаны с activeList,

Возможна ли такая оптимизация каким-либо образом?

1 ответ

Решение

Есть несколько разных ответов на этот вопрос.

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

Второе: да, отправка отдельного действия для каждого нажатия клавиши не особенно эффективна. Я справился с этим в своем собственном приложении, написав компонент более высокого порядка, который использует свое состояние для буферизации изменений, чтобы ускорить повторный рендеринг входных данных и отменить диспетчеризацию действий. У меня есть этот компонент, доступный в сущности - с тех пор я сделал пару обновлений, но это общая идея. Возможно, вы также захотите взглянуть на библиотеки, такие как React-Reformed, React-Form или React-Redux-Form, которые предоставляют некоторые похожие элементы, в которые, вероятно, было вложено больше работы, чем мой кусок кода.

Третье: похоже, что вы передаете массив "активных" элементов каждому отдельному компоненту-флажку и сравниваете индексы внутри этого компонента. Это не очень производительный образец. Лучшим подходом, вероятно, было бы, чтобы родительский компонент имел список идентификаторов, передавал идентификатор каждому подключенному дочернему элементу, и каждый дочерний элемент просматривал свои собственные данные по идентификатору в своем mapState, Посмотрите эти слайды на High-Performance Redux для получения дополнительной информации. У меня также есть другая информация о производительности Redux как часть моего списка ссылок React/Redux.

Другие вопросы по тегам