Warum wird die Bereinigungsfunktion von „useEffect“ bei jedem Rendern aufgerufen?
Lesezeit: 7 Minuten
Joji
Ich habe React gelernt und gelesen, dass die Funktion von zurückgegeben wurde useEffect ist für die Bereinigung gedacht und React führt die Bereinigung durch, wenn die Bereitstellung der Komponente aufgehoben wird.
Also habe ich ein wenig damit experimentiert, aber im folgenden Beispiel festgestellt, dass die Funktion jedes Mal aufgerufen wurde, wenn die Komponente erneut gerendert wurde, und nicht nur dann, wenn sie vom DOM getrennt wurde, d console.log("unmount"); jedes Mal, wenn die Komponente erneut gerendert wird.
React führt die Bereinigung durch, wenn die Bereitstellung der Komponente aufgehoben wird.
Ich weiß nicht, wo Sie das gelesen haben, aber diese Aussage ist falsch. React führt die Bereinigung durch, wenn sich die Abhängigkeiten zu diesem Hook ändern und der Effekt-Hook erneut mit neuen Werten ausgeführt werden muss. Dieses Verhalten ist beabsichtigt, um die Reaktivität der Ansicht auf sich ändernde Daten aufrechtzuerhalten. Gehen wir vom offiziellen Beispiel aus und nehmen wir an, eine App abonniert Statusaktualisierungen aus dem Profil eines Freundes. Da Sie der große Freund sind, der Sie sind, entscheiden Sie sich, die Freundschaft mit ihm zu beenden und sich mit jemand anderem anzufreunden. Jetzt muss die App die Statusaktualisierungen des vorherigen Freundes abbestellen und auf Aktualisierungen Ihres neuen Freundes hören. Dies ist natürlich und mit der Art und Weise leicht zu erreichen useEffect funktioniert.
Indem wir die Freundes-ID in die Abhängigkeitsliste aufnehmen, können wir angeben, dass der Hook nur ausgeführt werden muss, wenn sich die Freundes-ID ändert.
In Ihrem Beispiel haben Sie das angegeben array in der Abhängigkeitsliste und Sie ändern das Array in einem festgelegten Intervall. Jedes Mal, wenn Sie das Array ändern, wird der Hook erneut ausgeführt.
Sie können die richtige Funktionalität erreichen, indem Sie einfach das Array aus der Abhängigkeitsliste entfernen und die Callback-Version von verwenden setState Haken. Die Callback-Version arbeitet immer mit der vorherigen Version des Status, sodass der Hook nicht jedes Mal aktualisiert werden muss, wenn sich das Array ändert.
Ein zusätzliches Feedback wäre, die ID direkt zu verwenden clearInterval da der Wert geschlossen (erfasst) wird, wenn Sie die Bereinigungsfunktion erstellen. Es ist nicht erforderlich, es unter einer Referenz zu speichern.
Dieses Zitat „React führt die Bereinigung durch, wenn die Bereitstellung der Komponente aufgehoben wird.“ kommt direkt von React: reagierenjs.org/docs/hooks-effect.html
– Mike Portanova
14. März 2020 um 20:56
Lesen Sie weiter, Sie werden sehen, dass dies nicht nur der Fall ist, wenn die Komponente ausgehängt wird. Das ist der Punkt, den ich anspreche.
– Avin Kavish
15. März 2020 um 7:49 Uhr
Ich muss dies ablehnen, da die von Ihnen zitierte Aussage nicht falsch, sondern lediglich unvollständig ist. Außerdem stammt es aus den offiziellen Dokumenten, sodass es nicht hilfreich ist, zu unterstellen, dass sie etwas Falsches gelesen haben.
– Steinybot
31. Juli 2021 um 22:30 Uhr
Aus React: „React führt die Bereinigung durch, wenn die Komponente ausgehängt wird. Wie wir jedoch bereits erfahren haben, werden Effekte bei jedem Rendern ausgeführt und nicht nur einmal. Aus diesem Grund bereinigt React auch Effekte aus dem vorherigen Rendering, bevor die Effekte das nächste Mal ausgeführt werden.“ “
Kurz gesagt liegt der Grund darin, dass ein solches Design vor veralteten Daten und Aktualisierungsfehlern schützt.
Der useEffect Hook in React ist so konzipiert, dass er sowohl das erste Rendering als auch alle nachfolgenden Renderings verarbeitet (Hier erfahren Sie mehr darüber).
Effekte werden über ihre Abhängigkeiten gesteuert, nicht über den Lebenszyklus der Komponente, die sie verwendet.
Immer wenn sich Abhängigkeiten eines Effekts ändern, useEffect Bereinigt den vorherigen Effekt und führt den neuen Effekt aus.
Ein solches Design ist vorhersehbarer – Jedes Rendering hat seinen eigenen unabhängigen (reinen) Verhaltenseffekt. Dadurch wird sichergestellt, dass die Benutzeroberfläche immer die richtigen Daten anzeigt (da die Benutzeroberfläche im mentalen Modell von React ein Screenshot des Status für ein bestimmtes Rendering ist).
Die Art und Weise, wie wir Effekte steuern, erfolgt über ihre Abhängigkeiten.
Um zu verhindern, dass die Bereinigung bei jedem Rendern ausgeführt wird, dürfen wir lediglich die Abhängigkeiten des Effekts nicht ändern.
In Ihrem Fall konkret geschieht die Bereinigung, weil array ändert sich, d.h Object.is(oldArray, newArray) === false
useEffect(() => {
// ...
}, [array]);
// ^^^^^ you're changing the dependency of the effect
Sie bewirken diese Änderung mit der folgenden Zeile:
useEffect(() => {
const id = setInterval(() => {
setArray(array.concat("hello")); // <-- changing the array changes the effect dep
}, 3000);
myRef.current = id;
return () => {
clearInterval(myRef.current);
};
}, [array]); // <-- the array is the effect dep
Hallo, danke für deine Antwort. Das macht es klar. Aber wenn ich das nicht einstelle array als Abhängigkeit, d. h. ich lasse es als leeres Array, das setInterval wird nur einmal ausgeführt. Wissen Sie, wie man das beheben kann?
– Joji
13. Juli 2019 um 23:38 Uhr
Nun, das hängt davon ab, wann es laufen soll? Vielleicht setTimeout ist das, wonach Sie suchen?
– nem035
13. Juli 2019 um 23:42 Uhr
Vu Nguyen
Wie andere gesagt haben, hing der useEffect von den Änderungen des „Arrays“ ab, das im 2. Parameter im useEffect angegeben wurde. Wenn Sie es also auf ein leeres Array setzen, kann dies dazu beitragen, useEffect einmal auszulösen, wenn die Komponente bereitgestellt wird.
Der Trick besteht darin, den vorherigen Zustand des Arrays zu ändern.
Wenn ich mir den Code ansehe, könnte ich vermuten, dass es am zweiten Parameter liegt [array]. Da Sie es aktualisieren, wird ein erneutes Rendern aufgerufen. Versuchen Sie, ein leeres Array festzulegen.
Bei jeder Statusaktualisierung wird ein erneutes Rendern und Unmounten durchgeführt, und dieses Array ändert sich.
Mobeen
Es scheint erwartet zu sein. Gemäß der Dokumentation hier, useEffect wird nach dem ersten Rendern, jedem Update und Unmounten aufgerufen.
Wenn Sie mit den Lebenszyklusmethoden der React-Klasse vertraut sind, können Sie sich useEffect Hook als Kombination von ComponentDidMount, ComponentDidUpdate und ComponentWillUnmount vorstellen.
Archimedes Trajano
Dies ist ein Scherztest, der die Render- und Effektreihenfolge zeigt.
Wie Sie aus dem Erwarten ersehen können, ist einmal die Abhängigkeit foo Änderungen aufgrund der Statusaktualisierung lösen ein NEUES Rendering aus, gefolgt von der Bereinigungsfunktion des ersten Renderings.