Akita状态更新后组件为什么不重新渲染?
我用Akita做状态管理,修改store里的数据后,React组件居然没重新渲染,是不是哪里写错了?
我试过用update方法直接改对象属性,也试过用produce,但都没用。控制台打印新状态是对的,就是界面不动。
const { todos } = useTodosStore();
const addTodo = () => {
todosStore.update(state => ({
...state,
list: [...state.list, { id: Date.now(), text: 'new' }]
}));
};
// 组件里就直接用了 {todos.list.map(...)}
EntityStore用法上——你是不是用的是EntityStore而不是Store?如果是EntityStore,它默认是按 entity id 做变更检测的,直接list: [...state.list, newTodo]这种数组替换不会触发 React 重渲染,因为 Akita 内部比较的是entities的 id 集合,不是整个数组引用。先确认下你的 store 定义:
如果是这种:
那它内部会把
list当作entities的索引容器,实际数据存在entities对象里。这时候你得用addEntities或updateEntities:或者如果你坚持要用数组形式存
list,那就别用EntityStore,直接用普通Store:另外,
produce也能用,但得确保你返回的是新对象而不是改原对象,比如:不过要注意,
produce是 Immer 的 API,要确认你引入的是@datorama/akita的produce还是自己手动引入的,有些版本里update不配合 Immer 的produce直接用会失效。最后别忘了组件里订阅的时候是不是这样写的:
如果只是
const { todos } = useTodosStore()然后{todos.list},那todos对象本身引用没变,React 就不会重渲染——必须解构出具体的list才行,这点特别容易踩坑。总结下排查顺序:
1. 检查 store 类型(EntityStore 还是普通 Store)
2. 看组件订阅方式是不是解构了具体字段
3. 更新方式是否符合 store 类型的规范
4.
produce的使用是否正确我之前也卡在这过,Akita 文档没写清楚这个坑,EntityStore 和普通 Store 的行为差异太大了,稍微一不小心就白调一小时 API。