具有状态依赖性的 useCallback 会导致无限循环
useCallback with state dependency causes infinite loop
我有一个更新状态的 useCallback
,但是因为它需要将该状态作为依赖项,所以它在更新状态时创建了一个无限循环。我在这里使用 useImmer
,但在使用普通 useState
时也会发生这种情况。
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]);
基本上当添加或删除索引时,panels
发生变化,再次触发 onValidatePanel
,然后重新添加索引,如此等等……
我该如何解决这个问题?
我认为您根本不需要填充依赖项数组,您可以从功能状态更新程序函数中的 draft
副本访问 panels
状态。
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);
}
});
}, []);
我有一个更新状态的 useCallback
,但是因为它需要将该状态作为依赖项,所以它在更新状态时创建了一个无限循环。我在这里使用 useImmer
,但在使用普通 useState
时也会发生这种情况。
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]);
基本上当添加或删除索引时,panels
发生变化,再次触发 onValidatePanel
,然后重新添加索引,如此等等……
我该如何解决这个问题?
我认为您根本不需要填充依赖项数组,您可以从功能状态更新程序函数中的 draft
副本访问 panels
状态。
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);
}
});
}, []);