我正在使用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>
它不是更新/渲染视图。我该如何解决?
答案 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;
});