Redux中如何安全更新嵌套对象的属性?

Newb.青青 阅读 216

在用Redux管理用户资料时遇到了问题,用户资料结构是这样的:user: { name: 'John', address: { city: 'NY', zip: '10001' } }。当我尝试更新地址中的邮编时,这样写:


case UPDATE_ZIP:
  return {
    ...state,
    user: {
      ...state.user,
      address: {
        ...state.user.address,
        zip: action.zip
      }
    }
  }

但发现有时候旧数据还是会保留,比如修改两次后邮编会回到之前的值。我试过用immer的produce函数:


import produce from 'immer';
...
case UPDATE_ZIP:
  return produce(state, draft => {
    draft.user.address.zip = action.zip;
  });

但控制台报错说”immer: draft properties must be accessed through the draft parameter”。明明已经用了draft对象啊,这是哪里出错了?有没有更可靠的嵌套对象更新方法?

我来解答 赞 11 收藏
二维码
手机扫码查看
2 条解答
长孙芳芳
你的immer用法有问题,应该是draft直接操作而不是state。试试这个:

case UPDATE_ZIP:
return produce(state, draft => {
draft.user.address.zip = action.zip;
});


报错是因为你可能写成这样了:
draft.state.user.address.zip = action.zip
(错误写法)

如果不想用immer,用原生Redux也可以,但确实比较啰嗦。你之前的写法理论上没问题,但可能有其他reducer干扰。确保你的reducer是纯函数,不要在内部修改原state。

另外建议用redux-toolkit,内置了immer,写起来更简单:
const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
updateZip(state, action) {
state.user.address.zip = action.payload;
}
}
});


说实话,我刚开始用immer也经常踩这个坑,每次都在draft前面多写个state...
点赞
2026-03-10 04:01
爱学习的鑫玉
你这个问题主要是两个地方出错了。第一种写法的问题在于可能不小心直接修改了原始state,建议改用immer来简化操作;第二种写法报错是因为你的代码里可能有其他地方在访问state而不是draft,检查一下是不是有类似state.user这种直接引用。

推荐用immer的正确姿势如下:

import produce from 'immer';
...
case UPDATE_ZIP:
return produce(state, draft => {
draft.user.address.zip = action.zip;
});


如果还是有问题,那就别用嵌套结构了,把用户资料打平成{ name: 'John', city: 'NY', zip: '10001' }会省很多麻烦。数据结构简单点,少掉一堆坑。
点赞 7
2026-02-14 19:06