useEffect 依赖数组和 ESLint Exclusive-deps 规则

IT技术 reactjs react-hooks use-effect
2021-04-30 05:43:37

我有一个看起来像这样的组件:

const MyComponent = props => {
  const { checked, onChange, id } = props;
  const [isChecked, setChecked] = useState(false);

  useEffect(() => {
    onChange && onChange({ isChecked: !!checked, id });
    setChecked(checked);
  }, [checked]);

  const childProps = {
    id,
    isChecked
  };

  return <ChildComponent {...childProps} />;
};

详尽的 deps lint 规则并不令人满意:

React Hook useEffect 缺少依赖项:idonChange. 包括它们或删除依赖项数组。(react-hooks/exhaustive-deps)eslint

我知道这一点id并且onChange不会改变,因此将它们添加到依赖项数组似乎没有必要。但规则不是警告,而是明确的指示去做某事。

是 ESLint 规则:

1)在这种情况下过于谨慎和有点愚蠢,所以可以忽略吗?

2) 突出最佳实践——例如,如果父组件的变化意味着 id在未来的某个时刻发生变化,那么为了最大限度地减少将来可能发生的意外错误

3) 显示当前代码的实际/可能问题?

2个回答

实际上,规则非常简单:要么传递包含所有依赖项的数组,要么不传递任何内容。所以我猜这个规则不是愚蠢的,它只是不知道依赖项是否会改变。所以是的,如果你传递一个依赖项数组,它应该包含所有依赖项,包括那些你知道的不会改变的事实。像这样的事情会发出警告:

useEffect(() => dispatch({ someAction }), [])

要解决此问题,您应该将其dispatch作为依赖项传递,即使它永远不会改变:

useEffect(() => dispatch({ someAction }), [dispatch])

不要禁用详尽DEPS裁决,提到这里


更新 05/04/2021

正如这里所提到的这不再是必要的,因为 eslint pull #1950

现在具有稳定签名的引用类型,例如那些来自useStateuseDispatch可以安全地在效果内使用,exhaustive-deps即使来自效果也不会触发props

看待它的方式是每个渲染都有自己的效果。如果效果与一组特定的值相同,那么我们可以告诉 React 依赖项数组中的这些值。理想情况下,具有相同状态和props的组件在其渲染和效果完成后将始终具有相同的输出(渲染组件 + 效果)。这就是使它对错误更具弹性的原因。

规则的要点是,如果 deps DO 更改,则效果应该再次运行,因为它现在是不同的效果。

这 3 个链接也提供了更多关于此的见解: