React hook useEffect dependency array
我试图用新的react钩子api包住我的头。具体来说,我正在尝试构建曾经是以下情况的经典用例:
1 2 3 4 5 6 | componentDidUpdate(prevProps) { if (prevProps.foo !== this.props.foo) { // animate dom elements here... this.animateSomething(this.ref, this.props.onAnimationComplete); } } |
现在,我尝试使用功能组件和
1 2 3 | useEffect(() => { animateSomething(ref, props.onAnimationComplete); }, [props.foo]); |
这样,仅在props.foo更改时才调用效果。那确实有效,但是!由于
1 2 3 | useEffect(() => { animateSomething(ref, props.onAnimationComplete); }, [props.foo, ref, props.onAnimationComplete]); |
这不会导致掉毛错误,但完全无法实现仅在
现在,我读到一些有关使用
有人可以帮忙吗?
我建议编写如下:
1 2 3 4 5 6 7 8 | const previousFooRef = useRef(props.foo); useEffect(() => { if (previousFooRef.current !== props.foo) { animateSomething(ref, props.onAnimationComplete); previousFooRef.current = props.foo; } }, [props.foo, props.onAnimationComplete]); |
您无法避免在效果中包含条件的复杂性,因为如果没有条件,您将在mount上而不是仅在
通过在依赖项数组中包含
这是一个有效的示例:
抑制棉绒,因为它会给您一个不好的建议。 React要求您将第二个参数(仅更改)必须触发效果的值传递给第二个参数。
1 2 3 | useEffect(() => { animateSomething(ref, props.onAnimationComplete); }, [props.foo]); // eslint-disable-line react-hooks/exhaustive-deps |
得出的结果与Ryan的解决方案相同。
我认为违反这条短绒规则没有问题。与
您甚至可能希望在外部值发生变化时调用效果:
1 2 3 | useEffect(() => { alert(`Hi ${props.name}, your score is changed`); }, [props.score]); |
将在回调中必须是新鲜的(不陈旧)但不能重新激活效果的值移动到refs:
1 2 3 4 5 6 7 8 | const elementRef = useRef(); // Ex `ref` from the question const animationCompleteRef = useRef(); animationCompleteRef.current = props.onAnimationComplete; useEffect(() => { animateSomething(elementRef, animationCompleteRef.current); }, [props.foo, elementRef, animationCompleteRef]); |
之所以起作用,是因为