反应挂钩useEffect依赖数组

ove*_*b60 28 javascript reactjs react-hooks

我试图把头缠在新的react钩子api上。具体来说,我正在尝试构建一次经典的用例:

componentDidUpdate(prevProps) {
    if (prevProps.foo !== this.props.foo) {
        // animate dom elements here...
        this.animateSomething(this.ref, this.props.onAnimationComplete);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我尝试使用功能组件和构建相同的组件useEffect,但不知道如何实现。这是我尝试的:

useEffect(() => {
    animateSomething(ref, props.onAnimationComplete);
}, [props.foo]);
Run Code Online (Sandbox Code Playgroud)

这样,仅在props.foo更改时才调用效果。那确实有效–但是!由于将其eslint-plugin-react-hooks标记为错误,因此它似乎是反模式。效果内使用的所有依赖项都应在依赖项数组中声明。因此,这意味着我必须执行以下操作:

useEffect(() => {
    animateSomething(ref, props.onAnimationComplete);
}, [props.foo, ref, props.onAnimationComplete]);
Run Code Online (Sandbox Code Playgroud)

但这不会导致掉毛错误,但完全无法实现props.foo更改时调用效果的目的。我不希望在其他道具或裁判改变时调用它。

现在,我读到一些有关使用useCallback这种包装的信息。我试过了,但没有得到进一步的解决。

有人可以帮忙吗?

Rya*_*ell 14

我建议编写如下:

const previousFooRef = useRef(props.foo);

useEffect(() => {
    if (previousFooRef.current !== props.foo) {
       animateSomething(ref, props.onAnimationComplete);
       previousFooRef.current = props.foo;
    }
}, [props.foo, props.onAnimationComplete]);
Run Code Online (Sandbox Code Playgroud)

您无法避免在效果中包含条件的复杂性,因为如果没有条件,您将在安装上而不是仅在props.foo更改时运行动画。该条件还使您可以避免在其他情况props.foo发生变化时进行动画处理。

通过包含props.onAnimationComplete在依赖项数组中,可以避免禁用lint规则,该规则有助于确保您不会在将来引入与缺少依赖项有关的错误。

这是一个工作示例:

编辑动画

  • @giorgim linter 知道从 `useRef` 返回的值[不会在渲染之间改变](https://github.com/facebook/react/blob/v16.12.0/packages/eslint-plugin-react-hooks/src /ExhaustiveDeps.js#L230),因此引用不需要位于依赖项数组中。在示例沙箱中,您可以看到没有 eslint 警告,但如果从依赖项数组中删除“foo”,您确实会收到警告。 (3认同)
  • 您指的是什么复杂性?该条件是必要的,以避免在安装时发出动画。将回调添加到依赖项比禁用lint规则要复杂得多。的确,当前在依赖项数组中没有必要,但是随着时间的推移,此代码可能会以多种方式发展,这将变得很重要,并且禁用lint规则将使将来的错误发生的可能性更大。 (2认同)