【问题标题】:useCallback with state dependency causes infinite loop具有状态依赖的 useCallback 导致无限循环
【发布时间】:2021-07-13 22:05:51
【问题描述】:

我有一个更新状态的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,然后重新添加索引,如此循环......

我该如何解决这个问题?

【问题讨论】:

  • 要么将panels 状态分离为单独的activePanel 和validPanels 状态,要么不将panels 标记为回调的依赖项。我更喜欢前者。
  • 您能说明onValidatePanel 回调是如何连接的吗?因为更改 panels 只会重建回调,但实际上不会触发它...
  • 我对 immer(或 useImmer 钩子)不是很熟悉,但我的直觉是,如果您可以在功能更新中从草稿中访问 panels 状态,则可以完全消除对panels作为依赖,消除依赖循环。
  • 如果您想使用先前的状态(例如 panel.validPanels)计算状态的值,我会考虑使用 setState 的函数形式。您可以将先前的状态作为 arg 接收,而不是将其指定为依赖项。 (reactjs.org/docs/hooks-reference.html#functional-updates)
  • useCallback 本身不应触发无限循环。只有当你将它放在 useEffect 的依赖数组中时才会发生这种情况,并在该效果中称它为 unguarded。我想你有一个,但没有包括它?无论如何,功能状态更新可能是正确的方法,但需要考虑其他事项。

标签: javascript reactjs react-hooks usecallback


【解决方案1】:

我认为您根本不需要填充依赖数组,您可以从功能状态更新器函数中的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);
    }
  });
}, []);

【讨论】:

  • 拥有全面的依赖数组有时真的很痛苦,但 setState() 的基于回调的版本有时可以挽救生命,不是吗?
猜你喜欢
  • 2021-05-23
  • 2021-09-27
  • 1970-01-01
  • 1970-01-01
  • 2021-07-25
  • 2021-01-08
  • 1970-01-01
  • 2020-09-06
相关资源
最近更新 更多