25

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

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} />;
};

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

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

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

是 ESLint 规则:

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

2) 强调最佳实践——例如,如果父组件的更改意味着 id在将来的某个时间点会发生变化,则尽量减少将来可能发生的意外错误?

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

4

2 回答 2

22

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

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

为了解决这个问题,您应该dispatch作为依赖项传递,即使它永远不会改变:

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

不要禁用详尽的 deps 规则,如此处所述


2021 年 5 月 4 日更新

如此所述。自从 eslint pull #1950以来,这不再是必需的。

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

于 2019-07-10T14:41:35.670 回答
4

The way to look at it is every render has its own effect. If the effect will be the same with a particular set of values, then we can tell React about those values in the dependencies array. Ideally, a component with the same state and props, will always have the same output (rendered component + effect) after its render and effect is done. This is what makes it more resilient to bugs.

The point of the rule is that, if the deps DO change, the effect SHOULD run again, because it is now a different effect.

These 3 links also give more insights about this:

于 2019-07-10T14:57:26.330 回答