React Redux - Мутация Редуктора - PullRequest
       6

React Redux - Мутация Редуктора

0 голосов
/ 21 сентября 2018

У меня есть редуктор, в котором изменяется текущее состояние объекта путем создания мелкой копии.Редуктор работает, обновляя значение в хранимом объекте template, затем возвращая объект полного состояния.Редуктор действительно обновляет хранилище, и я могу видеть изменение при обновлении с постоянным состоянием, восстанавливаемым из localStorage.Однако компоненты, подписанные с использованием connect(), не получают повторную визуализацию.Как мне написать этот редуктор правильным способом, чтобы не изменять состояние?

редуктор:

case UPDATE_STYLE:
  // Update the style value of the template
  let newState = {
    ...state
  }
  newState
      .templates[action.payload.selectedTemplateType]
      .content[action.payload.selectedTemplate]
      .template
      .styles[action.payload.styleKey][action.payload.fieldKey]
      .value = action.payload.value;

  // mutated state - not firing rerenders
  return newState;

запуск вызова диспетчеризации (работает):

onStyleChange(styleKey, fieldKey, value){
    this.props.dispatch(
      updateStyle(selectedTemplateType, selectedTemplate, styleKey, fieldKey, value)
    );
  }

как дочерний компонент подключен (не рендеринг):

const mapStateToProps = (state) => ({
  templates: state.templates.templates,
  selectedTemplateType: state.templateTypeSelection.selectedTemplateType,
  selectedTemplate: state.templateSelection.selectedTemplate
})

export default connect(mapStateToProps)(Index)

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

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

let newState = { ...state, templates: {
  { ...state.templates, [action.payload.selectedTemplateType]: {
    { ...state.templates[action.payload.selectedTemplateType], content: {
      { ...state.templates[action.payload.selectedTemplateType].content, [ // and so on

По крайней мере, вы только создадите новый объект для того, что действительно изменилось.

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

Когда вы не хотите делать такой глубокий переход, на npm также есть модули глубокого слияния (просто google для «merge deep npm»);Я просто не пробовал ничего из этого ...

0 голосов
/ 21 сентября 2018

В вашем редукторе после обработки действия объект state.templateTypeSelection.selectedTemplateType является тем же объектом, даже если некоторые свойства глубоко внутри объекта изменились.Другие реквизиты имеют ту же проблему.Таким образом, для компонента реквизиты - это те же реквизиты, поэтому компонент не перерисовывается.

Есть несколько решений для этого.1 Чтобы сгладить ваше состояние редуктора.(кажется, не работает для вас) 2 Для глубокого копирования состояния редуктора.3 Когда вы выполняете `mapStateToProps, попробуйте отобразить самое внутреннее свойство вместо свойства верхнего уровня.

Для решения 2 вы можете создать классы для свойства верхнего уровня состояния редуктора.Например, вы можете создать класс с именем TemplateTypeSelection для state.templateTyepeSelection.Когда вы обрабатываете действия в редукторе, для нового состояния вы используете new TemplateTypeSelection(prevState.templateTypeSelection) для создания нового объекта для state.templateTypeSelection (вы можете использовать конструктор для создания поверхностной копии state.templateTypeSelection).Поскольку state.templateTypeSelection теперь является новым объектом, ваш компонент должен иметь возможность перерисовки.Проблема с этим методом заключается в том, что, поскольку каждый раз, когда вы обрабатываете действие, вы создаете новый объект, может возникнуть некоторая ненужная перерисовка.(Это всего лишь пример того, как это сделать. Возможно, это не очень хороший пример, потому что в вашем компоненте вы подключаете state.templateTypeSelection.selectedTemplateType, а не state.templateTypeSelection. Надеюсь, вы поняли идею.)

На основепо моему опыту, комбинация методов 2 и 3 работает лучше всего.Также вы можете разделить редуктор на несколько редукторов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...