Reagiere + useState () + previousState
Ich bin ziemlich neu in der Reaktion und habe Probleme, den useState-Hook zu verstehen - oder genauer gesagt den Aspekt des vorherigen Status .
Ein normaler useState Hook und wahrscheinlich das häufigste Beispiel sieht folgendermaßen aus:
import React, { useState} from 'react';
export default function CounterHooks({ initialCount }){
const [count, setCount] = useState(initialCount);
return (
<div>
<button onClick={() => setCount(count -1)}>-</button>
<span>{count}</span>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
)
}
Was ich bisher verstehe, ist folgendes:
- Ich rufe die useState () Funktion / Hook auf. und übergeben Sie das Argument des Anfangszustands (initialCount)
- Ich bekomme ein Array zurück, das ich sofort in die Variablen count und setCount (was Funktion ist) zerstöre.
- Mit setCount () kann ich den Status und damit die Zählvariable aktualisieren
So weit so gut, denke ich ...;)
Manchmal sehe ich das gleiche Gegenbeispiel mit prevState (prevCount), das ich nicht verstehe:
<button onClick={() => setCount(prevCount => prevCount -1)}>-</button>
was geschieht hier? Diesen Teil verstehe ich nicht. Meine bisherigen Gedanken:
- In diesem Fall greife ich irgendwie auf den vorherigen Zählwert zu.
- setCount erwartet nun eine Funktion
- setCount wird jetzt asynchron ausgeführt
- Woher kommt diese Funktion?
- Woher kommt prevCount?
- Was wird in prevCount abgelegt, wenn ich dies ausführe?
Verstehst du meine Verwirrung? Ich bin mir nicht sicher, wie ich das anders gestalten soll ...
Vielen Dank für Ihre Hilfe.
Antworten
Zunächst können Sie hier die offizielle Erklärung sehen .
In diesem Fall greife ich irgendwie auf den vorherigen Zählwert zu.
Sie greifen irgendwie nicht auf den vorherigen Zählwert zu. Wenn Sie eine Funktionsaktualisierung verwenden und dem Setter eine Rückruffunktion geben, wird der vorherige Status an Sie zurückgegeben, und Sie verwenden diesen Wert in Ihrer Rückruffunktion.
setCount erwartet nun eine Funktion
Da Sie eine Funktion bereitstellen, kann diese verwendet werden.
setCount wird jetzt asynchron ausgeführt
Nicht wirklich. Es ist keine asynchrone Funktion. Es stellt nur den vorherigen Status bereit und Sie verwenden ihn. Statussetzer sind nicht asynchron, die Statusaktualisierung ist.
Woher kommt diese Funktion?
Woher kommt prevCount?
Schon beantwortet.
Was wird in prevCount abgelegt, wenn ich dies ausführe?
Sie geben an, was Sie möchten, um den neuen Status dort zu setzen. In Ihrem Beispiel möchten Sie countum 1 erhöhen , damit Sie bereitstellen+ 1
Hier ist eine naive Erklärung für diese Logik. Nur eine naive. Ich füge dies hinzu, um die Rückruflogik zu veranschaulichen. Dies hängt nicht mit der von React zusammensetState.
let state = 5;
function setState(val) {
if (typeof val === "function") {
return val(state);
}
return val;
}
const stateWithFunctionalUpdate = setState(prev => prev + 1);
const stateWithNormalUpdate = setState(9);
console.log(stateWithFunctionalUpdate);
console.log(stateWithNormalUpdate);
Vielleicht wäre dieses Beispiel geeignet, um die Zustandseinstellungslogik der Reaktion nachzuahmen. Wieder nur ein naiver Ansatz.
let state = 5;
function setState(val) {
if (typeof val === "function") {
state = val(state);
} else {
state = val;
}
}
setState(9);
setState(prev => prev + 1);
console.log("state", state);
Schauen wir uns die tatsächliche Implementierung von useState(ohne Typisierung) an:
export function useState(initialState) {
return useReducer(
basicStateReducer,
// useReducer has a special case to support lazy useState initializers
initialState
);
}
Nun, es wird nur useReducerhinter den Vorhängen verwendet. Es legt den Anfangszustand fest und verwendet basicStateReducer :
function basicStateReducer(state, action) {
return typeof action === "function" ? action(state) : action;
}
Wie unser naiver Ansatz sucht er nach der Art der actionund verhält sich danach. Schließlich useReducer kehrt folgendes zurück :
return [workInProgressHook.memoizedState, dispatch];
Wenn wir also am Ende des Tages eine Funktion bereitstellen useState, nimmt sie diese und führt sie dann in unserem Status aus und gibt den Wert zurück.
Hier ist meine Meinung, wie ich verstehe:
In diesem Fall greife ich irgendwie auf den vorherigen Zählwert zu. -> setCount prüft param. Wenn es sich bei dem param um einen Rückruf handelt, ruft es diesen Rückruf auf und übergibt den vorherigen Status für param. Das Ergebnis des Rückrufs ist der nächste Status.
setCount erwartet jetzt eine Funktion -> Ja, die Funktion behandelt Ihre Logik und gibt den nächsten Status zurück.
setCount wird jetzt asynchron ausgeführt -> diese Funktion ist synchron, gibt jedoch das Ergebnis zurück. Der Hook für setCount löst ein Ereignis aus, um den nächsten Status zu aktualisieren
Woher kommt diese Funktion? -> Sie können alles in der Funktion tun, solange param der aktuelle Status ist und einen nächsten Status zurückgibt.
Woher kommt prevCount? -> wird beim Aufruf von setCount übergeben (es wird vom aktuellen Status abgerufen).
Was wird in prevCount abgelegt, wenn ich dies ausführe? -> aktueller Status von setCount.
=> Beispiel für die Übergabe eines Wertes oder eines Rückrufs an setCount hier: useState hook, setState function. Zugriff auf den vorherigen Statuswert