Dva中更新了state但组件没重新渲染,是什么原因?

A. 慧娇 阅读 32

在用Dva做用户列表时,更新了model里的users数组,但页面没变。检查过state确实有变化,订阅也确认了新旧值不同。之前加了CSS过渡效果,但去掉后还是不行。难道是连接model的方式有问题?代码看起来没问题啊…

尝试过手动调用dispatch方法:dispatch({ type: 'updateUsers', payload: newData }),控制台显示state更新了,但组件就是不渲染。是不是和immer库的使用有关?

附上相关CSS样式:


.user-list {
  transition: all 0.3s;
  opacity: 0.8;
}

我来解答 赞 6 收藏
二维码
手机扫码查看
2 条解答
码农永莲
这个问题大概率是跟React的immutable原则有关,官方文档里提到过state必须保持不可变性。你提到用了immer库,这其实是个关键点。如果在reducer里直接修改了state的引用而不是返回新的对象,即使数据内容变了,react-redux检测不到引用变化就不会触发重新渲染。

标准写法应该是这样,假设你在dva的reducers里更新users数组:
function updateUsers(state, { payload }) {
return { ...state, users: [...payload] };
}


或者用immer的话确保正确使用produce方法:
import produce from 'immer';

function updateUsers(state, { payload }) {
return produce(state, draft => {
draft.users = payload;
});
}


另外检查一下connect的写法,确保mapStateToProps里解构出的props是最新的。比如这样:
const mapStateToProps = ({ user }) => ({ users: user.users });

还有个常见的坑是如果你在组件里用了shouldComponentUpdate或者PureComponent,记得检查是不是误判了props的变化。

至于那个CSS过渡效果,倒是跟渲染问题没关系,不过建议把opacity改成1,0.8看着怪怪的。
点赞 1
2026-02-16 23:04
长孙佳杰
这个问题我之前也踩过坑。Dva 默认用 immer 做 state 不可变更新,如果你直接 push 或赋值方式不对,state 虽然变了但 immer 没触发 proxy 更新,组件就不会 rerender。

你更新 users 数组的时候有没有用展开运算符或者 immer 的 produce?比如:

const newUserList = [...state.users, newOne]

或者:

state.users.push(newOne)

后者在 immer 中是不会触发更新的,必须用前者。

还有一种情况是你可能在 model 里写了副作用逻辑,但没在 reducers 正确处理 action,比如写成异步逻辑没用 effects 或忘记 yield put。

另外,检查一下组件里 connect 的 model 是否正确绑定,比如:

export default connect(({ user }) => ({ users: user.users }))(UserList)

再确认一下 dispatch 的 action type 是否正确,比如:

dispatch({ type: 'user/updateUsers', payload: newUserList })

还有个排查方法是给组件加个 console.log(props),看 props 是否真的没更新。如果 props 更新了组件还没 rerender,那大概率是组件内部 shouldComponentUpdate 或 React.memo 拦住了。
点赞 10
2026-02-05 14:27