2016-11-03 3 views
0

ich Code wie folgt häufig schreiben (für Wiederverwendung):setState (..., Rückruf) ruft Rückruf vor Zustand gesetzt wurde

function doSomething() { 
    // I do something with this.state.MyVar 
} 

function buttonClicked(e) { 
    this.setState({MyVar: e.target.value}, this.doSomething()); 
} 

function otherEvent(e) { 
    this.setState({MyVar: e.target.value}, this.doSomething()); 
} 

Sobald doSomething() aufgerufen wird, ist es nicht ungewöhnlich, der Wert, der sich von dem von e.target.value unterscheidet. Es scheint, als ob der Rückruf tatsächlich nicht auftritt nach der Staat wurde aktualisiert?

Hinweis, das immer funktioniert:

function doSomething(value) { 
    // I do something with value 
} 

function buttonClicked(e) { 
    this.setState({MyVar: e.target.value}); 
    this.doSomething(e.target.value); 
} 

Dies ist in Google Chrome, und mit der neuesten Version von ReactJS.

Antwort

2

Die Klammern weglassen, da sie sofort die Funktion ausführen und den aufgelösten Wert (Rückgabewert) als Rückruf übergeben - was nicht erwünscht ist. Der Rückruf muss eine Funktion Referenz nicht Aufruf sein, da der Rückruf intern aufgerufen wird. Verwendung von Klammern, und Aufrufen somit folglich die Funktion es wird die Illusion der Ausführung sofort geben:

this.setState({MyVar: e.target.value}, doSomething); 
//            ^^ No parens! 

diese Weise doSomething ‚s Referenz wird anstelle eines Aufrufs übergeben, und es wird dementsprechend ausgeführt werden.


Beispiele für diese Art von Problemen können in vielen Fällen gesehen werden. Betrachten Sie diesen Code-Schnipsel:

document.getElementById("test").addEventListener("click", foo()); //to demonstrate the common mistake, let's try with parentheses 
 

 
function foo() { 
 
    console.log("I've been clicked (but not really!)"); 
 
}
<button id="test">Click me!</button>

Sie können sehen, dass wir einen Hörer-Taste #test hinzufügen, und es scheint, dass wir foo als Event-Handler einstellen, aber in Wirklichkeit führt sie sofort, obwohl wir es nicht angeklickt haben! Dies liegt daran, dass beim Ausführen des JavaScript-Befehls foo() sofort ausgeführt wird und somit zuvor I've been clicked (but not really!) protokolliert wird. Da die Funktion nichts zurückgibt, ist es gleichbedeutend mit:

document.getElementById("test").addEventListener("click", undefined); 

undefined wird als Event-Handler übergeben, weil der aufgelöste Wert als Event-Handler übergeben wird, und da die Funktion nichts zurückkehrte, war es undefined.

Dies kann hier angewendet werden, denn wenn Sie einen Aufruf für einen Rückruf übergeben, übergeben Sie tatsächlich den Rückgabewert dieser Funktion, weil Sie aufrufen es. Um dies zu bekämpfen, müssen Sie eine Referenz übergeben.

+0

Ah, dumm mich ... dachte, es wäre so etwas ... – Jay

+0

@Jay Der Rückruf wird ausgeführt, also eine Funktion * Referenz * benötigt wird. Wenn Sie es sofort aufrufen, versuchen Sie Folgendes: '();' – Li357

+0

Was passiert, wenn ich meine Anrufe umschließe, damit ich die Parameter behalten kann? this.setState ({MeineVar: "Hallo"}, Funktion() {MeineFunktion ("a", "b", "Hallo");}); – Jay