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

Wai*_*ein 3 javascript reactjs redux

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

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

_handleNameInput= (event) => {
     this.props.updateField({
             name: 'name',
             value: event.target.value,
     })
}
Run Code Online (Sandbox Code Playgroud)

在减速器中,我正在像这样更新状态字段

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

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

这是我的默认状态

let defaultState = {
     name: ''
}
Run Code Online (Sandbox Code Playgroud)

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

<h1>Name is: {this.props.name}</h1>
Run Code Online (Sandbox Code Playgroud)

上面的场景完全可以正常工作。当我也更改输入值时,它正在显示实时更改。当我在状态中使用嵌套对象时,问题就开始了。我将默认状态更新为此。

let defaultState = {
     form: {
        name: '',
     }
}
Run Code Online (Sandbox Code Playgroud)

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

this.props.updateField({
      name: 'form.name',
      value: event.target.value,
})
Run Code Online (Sandbox Code Playgroud)

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

<h1>{this.props.form.name}</h1>
Run Code Online (Sandbox Code Playgroud)

它不会更新/渲染视图。我该如何修复它?

lec*_*tor 5

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

第一个实例name是顶级 prop,它的更改被检测到,因此执行更新。

在第二个实例中form,顶级 prop 尚未更改,因此阻止了更新。

正如评论中所建议的,您可以使用它immer来确保该form对象被替换为具有更新name属性的新对象。

import produce from "immer";

return produce(state, draft => {
  _.set(draft, action.payload.name, action.payload.value);
});
Run Code Online (Sandbox Code Playgroud)

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

return {
  ...state,
  form: {
    ...state.form,
    name: action.payload.value
  }
};
Run Code Online (Sandbox Code Playgroud)

不过,我建议您重新考虑使用一个操作和减速器来更新任意深度嵌套的字段,而不是使用更具体的东西。

RESTAURANT_CATEGORY_UPDATE_FORM_FIELD

return {
  ...state,
  form: {
    ...state.form,
    [action.payload.name]: action.payload.value
  }
};
Run Code Online (Sandbox Code Playgroud)

或者

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