React hook использовать массив зависимостей useEffect - PullRequest
13 голосов
/ 18 марта 2019

Я пытаюсь обернуть голову вокруг новых крючков API реагировать. В частности, я пытаюсь создать классический вариант использования, который когда-то был следующим:

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

Теперь я попытался построить то же самое с компонентом функции и useEffect, но не могу понять, как это сделать. Вот что я попробовал:

useEffect(() => {
    animateSomething(ref, props.onAnimationComplete);
}, [props.foo]);

Таким образом, эффект вызывается только при изменении props.foo. И это работает - НО! Похоже, что это анти-шаблон, так как eslint-plugin-react-hooks помечает это как ошибку. Все зависимости, которые используются внутри эффекта, должны быть объявлены в массиве зависимостей. Это значит, что мне нужно сделать следующее:

useEffect(() => {
    animateSomething(ref, props.onAnimationComplete);
}, [props.foo, ref, props.onAnimationComplete]);

Это не приводит к ошибке линтинга, НО полностью исключает цель только , вызывающую эффект при изменении props.foo. Я НЕ ХОЧУ, чтобы его вызывали, когда другой реквизит или реф поменяли.

Теперь я прочитал кое-что об использовании useCallback, чтобы обернуть это. Я попробовал, но дальше не получилось.

Может кто-нибудь помочь?

Ответы [ 3 ]

6 голосов
/ 19 марта 2019

Я бы рекомендовал написать это следующим образом:

const previousFooRef = useRef(props.foo);

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

Вы не можете избежать сложности наличия условия внутри эффекта, потому что без него вы будете запускать анимацию при монтировании, а не только когда props.foo изменения.Условие также позволяет избежать анимации при изменении других элементов, кроме props.foo.

Включая props.onAnimationComplete в массив зависимостей, вы избегаете отключения правила lint, которое помогает избежать будущих ошибок, связанных с отсутствующими зависимостями.

Вот рабочий пример:

Edit animate

4 голосов
/ 19 марта 2019

Благодаря Райану, я понял это. Хотя я должен сказать - по крайней мере, в этом случае - я не вижу преимущества использования useEffect() по сравнению с классическим компонентом React с componentDidUpdate. Мне кажется, что версия с крючками в конце концов усложняет ситуацию. Поэтому я мог бы вернуться к версии компонента.

0 голосов
/ 19 марта 2019

ESLint не понимает ваш код или намерения. Ваш код должен работать нормально, как есть. Поэтому я предлагаю отключить eslint:

/* eslint-disable */
useEffect(() => {
    animateSomething(ref, props.onAnimationComplete);
}, [props.foo]);
/* eslint-enable */
...