我有一个化简器,其中通过创建浅表副本来改变当前状态对象的状态。减速器的工作方式是更新存储的对象template
中的值,然后返回完整状态的对象。 Reducer确实更新了存储,并且我能够看到刷新的更改,并且从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)
答案 0 :(得分:0)
在化简器中,处理完操作后,对象state.templateTypeSelection.selectedTemplateType
是同一对象,即使对象内部的某些属性发生了变化。其他道具也有同样的问题。因此,对于组件来说,道具是相同的道具,因此不会重新渲染组件。
有一些解决方案。 1使变径器状态变平。 (似乎不适合您)2要深度复制化简器状态。 3当执行mapStateToProps时,请尝试映射最里面的属性,而不是顶层属性。
对于解决方案2,您可以做的是为reducer状态的top属性创建类。例如,您可以为TemplateTypeSelection
创建一个名为state.templateTyepeSelection
的类。在reducer中处理动作时,对于新状态,请使用new TemplateTypeSelection(prevState.templateTypeSelection)
为state.templateTypeSelection创建一个新对象(您可能希望使用构造函数对state.templateTypeSelection
进行浅表复制)。由于state.templateTypeSelection现在是一个新对象,因此您的组件应该现在可以重新呈现。这种方法的问题在于,由于每次处理一个动作时,您都会创建一个新对象,因此可能会有一些不必要的重新渲染。 (这只是一个示例,可能不是一个好例子,因为在您的组件中,您连接的是state.templateTypeSelection.selectedTemplateType
,而不是state.templateTypeSelection
。希望您能明白。)
根据我的经验,方法2和3的组合效果最好。另外,您可能需要考虑将减速器分成几个减速器。
答案 1 :(得分:0)
另一篇文章已经提到使用深拷贝作为快速解决方案(尽管您可能会失去性能)。但是,尽管有些棘手,但扩展语法(...
)可能会为您带来帮助:
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表示“合并深npm”);我只是实际上没有尝试过任何一个...