我有一个关于 react + mobx + hooks API 没有正确更新状态的奇怪问题
这是下面示例的控制台输出。没关系 findDomNode 错误,与 toast 组件库过时有关
假设有一个服务列表和一组相应的 id。这是一个管理面板,我想在其中添加或删除服务器端的当前服务。我将选定的服务(即复选框)存储在 useState
中。也可以从后端删除服务,因此我需要使用后端响应中的内容更新前端的选定(复选框)列表
问题是显示更新就在 useEffect
内部的钩子,但在渲染函数 (handleListColCallback
) 内部 selected
的值没有更新,始终保留已删除的值
尝试了useMemo
、useCallback
等的多种组合,结果总是一样。我做错了什么吗?
const AdminServices = observer(() => {
const [selected, setSelected] = useState([]);
const serviceContext = useContext(ServiceStoreContext);
const handleListColCallback = async (params) => {
if (params.type === 'select-checkbox') {
// STEP 3 - I want to manipulate with state removing or adding checked id to array
// ERROR here - selected state still showing old value (not the same as in useEffect)
console.log('checkbox select', selected);
} else if (params.type === 'delete-from-node') {
// STEP 1 - I call delete action, it runs successfully
await serviceContext
.deleteFromNode({ service_id: params.id })
}
};
useEffect(() => {
// STEP 2 - when mobx store updates, I want to reset component state with new values
setSelected(serviceContext.nodeListArrayIds);
}, [serviceContext.nodeListArrayIds]);
useEffect(() => {
// selected shows current values (this effect is just for testing)
console.log('selected updated', selected);
}, [selected]);
}
更新
问题已通过使用以下 setState 和 handleListColCallback
更新解决。如果有人能解释为什么纯 setState
与 setState((curState) => ... )
useEffect(() => {
setSelected(() => {
return [...serviceContext.nodeListArrayIds];
});
}, [serviceContext.nodeListArrayIds]);
} else if (params.type === 'select-checkbox') {
setSelected((selected) => {
const index = selected.indexOf(params.id);
if (index === -1) {
return [...selected, ...[params.id]];
} else {
return selected.filter((x) => x !== params.id);
}
});
答案 0 :(得分:1)
上下文中的数组 (serviceContext.nodeListArrayIds
) 似乎以某种方式重新添加了已删除的项目(OP 可能想要调查的内容)。
setSelected(serviceContext.nodeListArrayIds);
和 setSelected([...serviceContext.nodeListArrayIds]);
之间的区别在于,在第一种情况下,selected
是对 serviceContext.nodeListArrayIds
的引用,因此将反映对它的任何更改。 [...serviceContext.nodeListArrayIds]
创建一个浅层克隆(类似于 .slice()
),因此对 serviceContext.nodeListArrayIds
的更改不会影响它。