BEARBEITEN (22. Juni 2020): Da diese Frage ein erneutes Interesse hat, ist mir klar, dass es einige Verwirrung geben kann. Daher möchte ich hervorheben: Das Beispiel in der Frage ist als Spielzeugbeispiel gedacht. Es spiegelt das Problem nicht wider. Das Problem, das diese Frage ausgelöst hat, liegt in der Verwendung einer Bibliothek eines Drittanbieters (über die nur eine begrenzte Kontrolle besteht), die einen Rückruf als Argument für eine Funktion verwendet. Was ist der richtige Weg, um diesen Rückruf mit dem neuesten Status bereitzustellen. In Reaktionsklassen würde dies durch die Verwendung von erfolgen this
. In React-Hooks ist der Zustand aufgrund der Art und Weise in den Funktionen von gekapselt React.useState()
wenn ein Rückruf bekommt der Staat durch React.useState()
, ist es veraltet (der Wert, als der Rückruf eingerichtet wurde). Aber wenn es setzt dem Zustand, hat er über das übergebene Argument Zugriff auf den neuesten Zustand. Dies bedeutet, dass wir möglicherweise den neuesten Status in einem solchen Rückruf mit React-Hooks von abrufen können Einstellung der Zustand soll derselbe sein wie er war. Das funktioniert, ist aber kontraintuitiv.
— Ursprüngliche Frage geht weiter unten —
Ich verwende React-Hooks und versuche, den Status innerhalb eines Callbacks zu lesen. Jedes Mal, wenn der Callback darauf zugreift, ist es auf seinen Standardwert zurückgesetzt.
Mit folgendem Code. Die Konsole druckt weiter Count is: 0
egal wie oft ich klicke.
function Card(title) {
const [count, setCount] = React.useState(0)
const [callbackSetup, setCallbackSetup] = React.useState(false)
function setupConsoleCallback(callback) {
console.log("Setting up callback")
setInterval(callback, 3000)
}
function clickHandler() {
setCount(count+1);
if (!callbackSetup) {
setupConsoleCallback(() => {console.log(`Count is: ${count}`)})
setCallbackSetup(true)
}
}
return (<div>
Active count {count} <br/>
<button onClick={clickHandler}>Increment</button>
</div>);
}
const el = document.querySelector("#root");
ReactDOM.render(<Card title="Example Component" />, el);
Sie können diesen Code finden hier
Ich hatte kein Problem damit, den Status innerhalb eines Rückrufs festzulegen, nur beim Zugriff auf den neuesten Status.
Wenn ich raten müsste, würde ich denken, dass jede Zustandsänderung eine neue Instanz der Card-Funktion erstellt. Und dass sich der Rückruf auf den alten bezieht. Basierend auf der Dokumentation unter https://reactjs.org/docs/hooks-reference.html#functional-updates, hatte ich die Idee, setState im Callback aufzurufen und eine Funktion an setState zu übergeben, um zu sehen, ob ich von setState aus auf den aktuellen Status zugreifen kann. Ersetzen
setupConsoleCallback(() => {console.log(`Count is: ${count}`)})
mit
setupConsoleCallback(() => {setCount(prevCount => {console.log(`Count is: ${prevCount}`); return prevCount})})
Sie können diesen Code finden hier
Auch dieser Ansatz hat nicht funktioniert. EDIT: Eigentlich dieser zweite Ansatz tut Arbeit. Ich hatte nur einen Tippfehler in meinem Rückruf. Das ist der richtige Ansatz. Ich muss setState aufrufen, um auf den vorherigen Zustand zuzugreifen. Auch wenn ich nicht die Absicht habe, den Zustand festzulegen.
Ich habe das Gefühl, dass ich mit React-Klassen ähnliche Ansätze verfolgt habe, aber. Aus Gründen der Codekonsistenz muss ich bei React Effects bleiben.
Wie kann ich von einem Callback aus auf die neuesten Statusinformationen zugreifen?
Ich glaube nicht, dass es ein Duplikat von oben ist. Da es nicht um die Tatsacheneinstellung geht, ist der Zustand asynchron. Aber über den Staat bis in alle Ewigkeit in einem Rückruf veraltet sein. Jetzt, wo ich die Antwort herausgefunden habe, kann es sich jedoch um ein Duplikat von stackoverflow.com/questions/56782079/react-hooks-stale-state handeln. Ich denke jedoch, dass dies auf eine interessante Folge davon hinweist, wie Reaktionshaken den Status verwalten. nämlich, dass Sie eine Funktion aufrufen müssen, die den Zustand festlegt, um innerhalb eines Rückrufs auf den richtigen Zustand zuzugreifen. Und das gilt auch dann, wenn Sie nicht die Absicht haben, den Zustand zu ändern.
– Stange
9. September 2019 um 4:02 Uhr
ja, du hast recht, es geht darum, wie Funktionsschließung funktioniert. hier ist eines der Themen zu diesem stackoverflow.com/questions/57471987/…
– Himmelsjunge
9. September 2019 um 4:42 Uhr
Vielleicht hilft dieser Blog von Dan Abramov: overreacted.io/making-setinterval-declarative-with-react-hooks, erklärt es, warum das Mischen von Hooks und setInterval wirklich verwirrend ist und zunächst nicht zu funktionieren scheint. TL:DR im Grunde wegen der Schließung müssen Sie den Rückruf mit dem nächsten Zustandswert “erneut einschließen”.
– Zeichnete Reese
9. September 2019 um 5:01 Uhr
Ja, ich dachte, es war etwas in dieser Richtung, als ich gebunden hätte
this
zum Rückruf, wenn ich Klassen verwendet habe, aber nicht sehen konnte, wie man es mit Effekten macht. Ich habe Ansätze wie das Einschließen von Gettern in die Zustandsvariable als Argument für den Rückruf ausprobiert. Aber nichts funktionierte. Jedenfalls ist mir nach Überprüfung aller Links, die alle geteilt haben, immer noch etwas nicht klar. Gibt es keine Möglichkeit, den Zustand der Komponente einfach aus einem anderen Kontext zu lesen, als durch Aufrufen ihrer Zustandseinstellungsfunktion (insbesondere wenn ich dies tue nicht möchte seinen Zustand ändern)?– Stab
9. September 2019 um 6:28 Uhr
In einigen Szenarien wäre es nicht richtiger, die zu verwenden
useReducer()
Haken dafür? In meinem Fall habe ich einen Rückruf an eine Bibliothek übergeben, die bei Nachrichten von vom Server gesendeten Ereignissen ausgelöst wird. Wenn eine Nachricht beim Client ankommt, wird der Rückruf ausgelöst und an die vorhandene gesendetmessages
Zustand.– Gjert
22. August 2020 um 7:39 Uhr