Clashing useEffects?

Sep 22 2020

Ich habe das Gefühl, dass ich oft auf dieses Problem stoße.

Beim Verketten von useEffects, die nach Statusänderungen ausgelöst werden sollen, stelle ich fest, dass einige der useEffects in der Kette überlappende Abhängigkeiten aufweisen, die dazu führen, dass beide nach dem Festlegen des Status ausgelöst werden und nicht nacheinander.

Beispiel: Ich löse beim chapterIndexAktualisieren eine Kette von useEffects aus .

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

Wie verhindere ich, dass beide bei chapterIndexÄnderungen ausgeführt werden? Ich möchte nur, dass der zweite useEffect ausgeführt wird, nachdem der erste useEffect auf textTransitioning gesetzt wurde. Beim Entfernen chapterIndexaus dem Abhängigkeitsarray wird folgende Fehlermeldung angezeigt : 'React Hook useEffect hat eine fehlende Abhängigkeit:' ChapterIndex '. Schließen Sie es entweder ein oder entfernen Sie das Abhängigkeitsarray. '

Antworten

Itaywazana Sep 22 2020 at 09:54

useEffectnimmt 2 Argumente. Das erste ist die aufzurufende Funktion und das zweite ist ein Array von Variablen, das als Abhängigkeitsarray bezeichnet wird. Das zweite Argument, das zum Auslösen des Verwendungseffekts verwendet wird, während sich eine der Variablen im Array ändert. Wenn Sie also nicht useEffectaufgerufen werden möchten , wenn eine bestimmte Variable geändert wird, übergeben Sie sie nicht im Abhängigkeitsarray. Ihr Code sollte so sein:

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]

Ich denke, das ist nicht sehr effizient, um das eine useEffectzum anderen auszulösen, aber vielleicht sehe ich nicht das ganze Bild

YogeshChaturvedi Sep 22 2020 at 09:58

Sie müssen "ChapterIndex" in Second UseEffect aus dem Array entfernen. Wenn also firstEEffect ausgeführt wird, wird die "textTransitioning" aktualisiert, die den zweiten useEffect-Trigger verursacht.

Weitere Informationen zur bedingten Ausführung von useEffect finden Sie unter https://reactjs.org/docs/hooks-effect.html