Reputation: 7727
I’ve got a useCallback
that updates state, but because it requires that state as a dependency, it creates an infinite loop when it updates the state. I’m using useImmer
here, but it happens when using plain useState
, too.
const [panels, updatePanels] = useImmer({
activePanel: 0,
validPanels: [],
});
const onValidatePanel = useCallback(isValid => {
const panelIndex = panels.validPanels.indexOf(panels.activePanel);
// Add
if (panelIndex === -1 && isValid) {
updatePanels(draft => {
draft.validPanels.push(draft.activePanel);
});
// Remove
} else if (panelIndex > -1 && !isValid) {
updatePanels(draft => {
draft.validPanels.splice(panelIndex, 1);
});
}
}, [panels]);
Basically when an index is added or removed, panels
changes, triggers onValidatePanel
again, and re-adds the index, and on and on…
How might I work around this?
Upvotes: 1
Views: 1226
Reputation: 203542
I don't think you need the dependency array populated at all, you can access the panels
state from the draft
copy in the functional state updater function.
const onValidatePanel = useCallback(isValid => {
updatePanels(draft => {
const panelIndex = draft.validPanels.indexOf(draft.activePanel);
if (panelIndex === -1 && isValid) {
// Add
draft.validPanels.push(draft.activePanel);
} else if (panelIndex > -1 && !isValid) {
// Remove
draft.validPanels.splice(panelIndex, 1);
}
});
}, []);
Upvotes: 1