¿Efectos en conflicto?

Sep 22 2020

Siento que me encuentro con este problema a menudo.

Al encadenar useEffects para que se activen después de los cambios de estado, encuentro que algunos de los useEffects en la cadena tienen dependencias superpuestas que hacen que ambos se activen en lugar de secuencialmente, después de que uno se establece en el estado.

Ejemplo: estoy activando una cadena de useEffects cuando se chapterIndexactualiza.

let [ chapterIndex, setChapterIndex ] = useState<number | null>(0);

let [textTransitioning, setTextTransitioning] = useState<'out' | 'in' | null>(null);

useEffect(() => {
    setTextTransitioning('out')
}, [chapterIndex])

useEffect(() => {
    if (chapterIndex !== null) {
        const {
            current: chapter = null
        } = chapterRefs.current[chapterIndex];
            
        if (textTransitioning === 'in') {
            chapter?.classList.add('in');
        }
    }
}, [textTransitioning, chapterIndex])

¿Cómo evito que ambos se ejecuten cuando chapterIndexcambia? Solo quiero que el segundo useEffect se ejecute después del primer useEffect se establece en textTransitioning. Al eliminar chapterIndexde la matriz de dependencias, aparece el error: 'React Hook useEffect tiene una dependencia faltante:' ChapterIndex '. Inclúyalo o elimine la matriz de dependencia '.

Respuestas

Itaywazana Sep 22 2020 at 09:54

useEffecttoma 2 argumentos. la primera es la función a invocar y la segunda es una matriz de variables llamada matriz de dependencias. el segundo argumento utilizado para activar el efecto de uso mientras una de las variables de la matriz está cambiando. por lo tanto, si no desea useEffectque lo llamen cuando se cambia una variable específica, no la pase en la matriz de dependencias. tu código debería ser así:

let [ chapterIndex, setChapterIndex ] = useState<number | null>(0);

let [textTransitioning, setTextTransitioning] = useState<'out' | 'in' | null>(null);

useEffect(() => {
      setTextTransitioning('out')
}, [chapterIndex])

useEffect(() => {
 if (chapterIndex !== null) {
     const {
         current: chapter = null
     } = chapterRefs.current[chapterIndex];
         
     if (textTransitioning === 'in') {
         chapter?.classList.add('in');
     }
 }
}, [textTransitioning]

Creo que no es muy eficiente hacer que uno useEffectactive el otro, pero tal vez no estoy viendo la imagen completa.

YogeshChaturvedi Sep 22 2020 at 09:58

Necesita eliminar "ChapterIndex" de la matriz en el segundo useEffect. Entonces, cuando se ejecute el primer useEffect, se actualizará el "textTransitioning" que causará el segundo disparador useEffect.

Para una ejecución más condicional de useEffect puede consultar https://reactjs.org/docs/hooks-effect.html