Zderzające się efekty użytkowania?

Sep 22 2020

Mam wrażenie, że często spotykam się z tym problemem.

Podczas łączenia w łańcuch useEffects, które mają być wyzwalane po zmianie stanu, stwierdzam, że niektóre z właściwości useEffects w łańcuchu mają nakładające się zależności, które powodują, że oba są wyzwalane, a nie sekwencyjnie, po ustawieniu stanu.

Przykład: Uruchamiam łańcuch efektów użycia podczas chapterIndexaktualizacji.

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])

Jak mogę zapobiec uruchamianiu obu po chapterIndexzmianach? Chcę, aby drugi element useEffect był uruchamiany po ustawieniu pierwszego elementu useEffect na tekstTransitioning. Podczas usuwania chapterIndexz tablicy zależności pojawia się błąd: „React Hook useEffect ma brakującą zależność:„ ChapterIndex ”. Dołącz go lub usuń tablicę zależności. '

Odpowiedzi

Itaywazana Sep 22 2020 at 09:54

useEffectprzyjmuje 2 argumenty. pierwsza to funkcja do wywołania, a druga to tablica zmiennych zwana tablicą zależności. drugi argument używany do wywołania efektu użycia, gdy jedna ze zmiennych w tablicy się zmienia. więc jeśli nie chcesz useEffectbyć wywoływany po zmianie określonej zmiennej, nie przekazuj jej w tablicy zależności. Twój kod powinien wyglądać tak:

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]

Myślę, że useEffectwywołanie jednego wyzwalania drugiego nie jest zbyt wydajne, ale może nie widzę całego obrazu

YogeshChaturvedi Sep 22 2020 at 09:58

Musisz usunąć „sectionIndex” z tablicy w drugim useEffect. Tak więc przy pierwszym uruchomieniu useEffect zaktualizuje parametr „textTransitioning”, który spowoduje drugi wyzwalacz useEffect.

Aby uzyskać bardziej warunkowe wykonanie useEffect, możesz odwołać się https://reactjs.org/docs/hooks-effect.html