在React Redux中更新嵌套对象的字段不会重新渲染视图(UI)

时间:2018-12-29 23:11:58

标签: javascript reactjs redux

我正在使用React和Redux作为前端JavaScript框架来开发Web应用程序。我在渲染视图和更新Redux状态/存储值时遇到了一些问题。

我有一个输入字段,用于更新Redux状态值。这是我的文本字段的onChange的事件处理程序。

_handleNameInput= (event) => {
     this.props.updateField({
             name: 'name',
             value: event.target.value,
     })
}

在reducer中,我正在像这样更新状态字段

case RESTAURANT_CATEGORY_UPDATE_FIELD: {
            let freshState = { ...state };
            _.set(freshState, action.payload.name, action.payload.value);
            return freshState;
        }

我正在使用Lodash更新状态对象的字段。

这是我的默认状态

let defaultState = {
     name: ''
}

当用户输入输入时,我会在这样的视图上显示实时状态值。

<h1>Name is: {this.props.name}</h1>

以上情况完全正常。它也在显示实时更改,同时我也在更改输入值。当我在状态中使用嵌套对象时,问题就开始了。我将defaultState更新为此。

let defaultState = {
     form: {
        name: '',
     }
}

然后在回调中,我这样更新。

this.props.updateField({
      name: 'form.name',
      value: event.target.value,
})

它正在更新对象嵌套属性的redux状态/存储值。问题是当我显示实时更改时

<h1>{this.props.form.name}</h1>

它不是更新/渲染视图。我该如何解决?

1 个答案:

答案 0 :(得分:2)

当您通过connect函数将组件连接到redux时,您的组件将表现为PureComponent。也就是说,它将对新道具进行浅层检查,并将其与以前的道具进行比较,以查看组件是否应该执行更新。

首先,name是顶级道具,并且会检测到其更改,因此将执行更新。

在第二个实例中,form是顶级道具,它没有更改,因此阻止了更新。

如注释中所建议,您可以使用immer确保form对象被具有更新后的name属性的新对象替换。

import produce from "immer";

return produce(state, draft => {
  _.set(draft, action.payload.name, action.payload.value);
});

在第二种情况下,它将有效地执行以下操作。

return {
  ...state,
  form: {
    ...state.form,
    name: action.payload.value
  }
};

不过,我建议您重新考虑使用一个动作和reducer来任意更新深层嵌套的字段,而使用更具体的内容。

RESTAURANT_CATEGORY_UPDATE_FORM_FIELD

return {
  ...state,
  form: {
    ...state.form,
    [action.payload.name]: action.payload.value
  }
};

return produce(state, draft => {
  draft.form[action.payload.name] = action.payload.value;
});