Reputation: 2544
I have a weird issue with react + mobx + hooks API not updating state correctly
This is a console output of the example below. Nevermind about findDomNode error, it's related to toast component library being out of date
Let's say there is a list of services and an array of corresponding ids. It's an admin panel where I want to add or delete current services on the server-side. I store selected services (i.e. checkboxes) in useState
. It's also possible to remove service from the backend and therefore I need to update the selected (checkboxed) list on the frontend with what comes in a backend response
The problem is that hook showing that update is right inside useEffect
, but inside render function (handleListColCallback
) selected
values is not updating, always keeping deleted values
Have tried multiple combinations of useMemo
, useCallback
, etc. There result is always the same. Am I doing something wrong?
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]);
}
UPDATE
Issue solved by using following setState and handleListColCallback
update. Would be happy if somebody could explain the difference why pure setState
is that different vs 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);
}
});
Upvotes: 1
Views: 715
Reputation: 5036
It appears that the array in the context (serviceContext.nodeListArrayIds
) somehow gets the deleted item re-added (something the OP might want to investigate).
The difference between setSelected(serviceContext.nodeListArrayIds);
and setSelected([...serviceContext.nodeListArrayIds]);
is that in the first case selected
is a reference to serviceContext.nodeListArrayIds
and thus will reflect any changes to it. [...serviceContext.nodeListArrayIds]
creates a shallow clone (similar to .slice()
), so changes to serviceContext.nodeListArrayIds
do not affect it.
Upvotes: 1