Problemcode Schauen Sie sich den Code eines durch useEffect verursachten Closure-Problems an. const btn = useRef(); const [v, setV] = useState(''); useEffect(() => { let clickHandle = () => { Konsole.log('v:', v); } btn.current.addEventListener('klicken', KlickHandle) zurückgeben () => { btn.removeEventListener('click', KlickHandle) } }, []); const inputHandle = e => { setV(e.Ziel.Wert) } zurückkehren ( <> <Eingabewert={v} beiÄnderung={inputHandle} /> <button ref={btn} >Testen</button> </> ) Das Abhängigkeitsarray von useEffect ist leer, sodass der interne Code nur einmal ausgeführt wird, nachdem das Rendern der Seite abgeschlossen ist, und noch einmal, wenn die Seite zerstört wird. Geben Sie zu diesem Zeitpunkt ein beliebiges Zeichen in das Eingabefeld ein und klicken Sie auf die Testschaltfläche. Die Ausgabe ist leer. Unabhängig davon, welche Zeichen Sie anschließend eingeben und erneut auf die Testschaltfläche klicken, ist das Ausgabeergebnis immer noch leer. Warum passiert das? Tatsächlich wird es durch die Schließung verursacht. UrsacheDer Gültigkeitsbereich einer Funktion wird bei der Definition der Funktion festgelegt. Beim Registrieren eines Klickereignisses für btn ist der Umfang wie folgt: Die zugängliche freie Variable v ist zu diesem Zeitpunkt noch null. Wenn ein Klickereignis ausgelöst wird, wird die Klick-Rückruffunktion ausgeführt. Zu diesem Zeitpunkt wird zuerst der Ausführungskontext erstellt und die Bereichskette in den Ausführungskontext kopiert.
Szene generieren
Lösung Hier sind 5 Lösungen für dieses Schließungsproblem: 1. Ändern Sie v direkt durch Zuweisung und umschließen Sie die Methode, die v ändert, mit useCallback Umschließen Sie die Methode, die v ändert, mit useCallback. Die von useCallback umschlossene Funktion wird zwischengespeichert. Da das Array der Abhängigkeiten leer ist, ist das hier durch direkte Zuweisung geänderte v das alte v. Diese Methode wird nicht empfohlen, da setState die offiziell empfohlene Methode zum Ändern des Status ist. Hier wird setV immer noch nur verwendet, um ein erneutes Rendern auszulösen. // Ändern Sie die Deklaration von v von const in var, um eine direkte Änderung zu ermöglichen var [v, setV] = useState(''); const inputHandle = useCallback(e => { let { Wert } = e.Ziel v = Wert setzeV(Wert) }, []) 2. Fügen Sie v zu den Abhängigkeiten von useEffect hinzu Dies ist möglicherweise die erste Lösung, die den meisten Leuten in den Sinn kommt. Da v alt ist, warum wird das Ereignis nicht bei jeder Aktualisierung von v neu registriert? Dies führt jedoch bei jeder Aktualisierung von v zu einer Neuregistrierung. Theoretisch wird ein Ereignis, das nur einmal registriert werden muss, mehrfach registriert. 3. Vermeiden Sie die erneute Deklaration von v Deklarieren Sie eine Variable anstelle von v mit let oder var und ändern Sie die Variable direkt, anstatt das Rendern mit setState-bezogenen Funktionen auszulösen. Auf diese Weise wird die Variable nicht erneut deklariert und der „neueste“ Wert kann in der Klick-Callbackfunktion abgerufen werden. Diese Methode wird jedoch nicht empfohlen. Für dieses Beispiel zeigt die Eingabekomponente immer einen leeren Wert an, da kein erneutes Rendern erfolgt, was nicht der erwarteten Operation entspricht. 4. Verwenden Sie useRef anstelle von useState const btn = useRef(); const vRef = useRef(''); const [v, setV] = useStat(''); useEffect(() => { let clickHandle = () => { console.log('v:', vRef.current); } btn.current.addEventListener('klicken', KlickHandle) zurückgeben () => { btn.removeEventListener('click', KlickHandle) } }, []); const inputHandle = e => { let { Wert } = e.Ziel vRef.current = Wert setzeV(Wert) } zurückkehren ( <> <Eingabewert={v} beiÄnderung={inputHandle} /> <button ref={btn} >Testen</button> </> ) Der Grund, warum die useRef-Lösung effektiv ist, liegt darin, dass jede Eingabeänderung die aktuelle Eigenschaft des vRef-Objekts ändert und vRef immer dieses vRef ist, auch wenn es erneut gerendert wird. Da vRef ein Objekt ist, ist der Wert der im Stapelspeicher gespeicherten Variablen die Adresse des Objekts im Heap-Speicher, die nur eine Referenz ist. Es wird nur eine bestimmte Eigenschaft des Objekts geändert, und die Referenz ändert sich nicht. Die Scope-Kette im Click-Event greift also immer auf dieselbe vRef zu. 5. Ersetzen Sie v durch einen Objekttyp Tatsächlich ist es genau wie bei der Verwendung von useRef so, dass, solange es sich um ein Objekt handelt, das Ändern nur eines bestimmten Attributs nicht die vom Status gezeigte Adresse ändert. Code-AdresseKlicken Sie hier, um den Testcode anzuzeigen Dies ist das Ende dieses Artikels über die Fallstricke von React UseEffect Closure. Weitere relevante Inhalte zu React UseEffect Closure finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird! Das könnte Sie auch interessieren:
|
>>: So geben Sie Parametervariablen extern im Docker an
Im vorherigen Artikel haben wir darüber geschrieb...
Einführung in CentOS CentOS ist eine Linux-Distri...
Wenn Sie in CSS die Eigenschaft „font-family“ ver...
<br />Struktur und Hierarchie reduzieren die...
Layoutteil: <div id="Schieberegler"&...
MySQL x64 stellt kein Installationsprogramm berei...
Perfekte Lösung für das skalierbare Spaltenproble...
MySQL-Filterungs-Timing von Where-Bedingungen und...
Klicken Sie auf die Schaltfläche, um den Text in ...
MySQL-Fehler: Fehlercode: 1293 Falsche Tabellende...
1. Hintergrund Sysbench ist ein Stresstest-Tool, ...
Vorbereiten: Downloadadresse für das MySQL 8.0 Wi...
Erstellen Sie eine neue server.js Garn init -y Ga...
Vorwort Ich muss dem Markodwn-Editor, den ich ger...
Inhaltsverzeichnis 1. Abhängigkeiten installieren...