2017-06-05 3 views
4

Im React tutorial, heißt esWarum müssen Ereignishandler Referenzen und keine Aufrufe sein?

onClick={alert('click')} Doing sofort statt alarmieren würde, wenn die Schaltfläche geklickt wird.

class Square extends React.Component { 
    render() { 
    return (
     <button className="square" onClick={() => alert('click')}> 
     {this.props.value} 
     </button> 
    ); 
    } 
} 

Allerdings kann ich nicht verstehen, warum das wäre ... kann mir jemand klären Sie dies bitte? Warum können Sie einen Funktionsaufruf nicht als Handler übergeben?

+0

'alert ('click')' ist ein Funktionsaufruf. React liest es und führt es sofort aus. Sie sollten stattdessen einen Verweis auf eine benannte Funktion übergeben. Also, 'this.myFunction' anstelle von' this.myFunction() '. Alternativ können Sie auf eine anonyme Funktion verweisen, die Sie in Ihren ursprünglichen Beitrag einfügen. – glhrmv

Antwort

9

Wenn Sie das tun onClick={alert("click")}, die die alert Funktion und weisen Sie den Rückgabewert (undefined) an die onClick Eigenschaft nennen los ist. Also, was React sieht ist onClick={undefined} und sagt: Nun, das ist keine Funktion, warum würde ich solch einen Handler hinzufügen?

Was Sie an onClick weitergeben möchten, ist eine Funktion, nicht undefined.

Deshalb müssen Sie tun: onClick={myFunction} wo myFunction() => alert("...") sein können, wie Sie erwähnt haben, oder Sie können bind verwenden eine ähnliche Funktion zu erstellen:

onClick={alert.bind(window, "click")} 

bind wird Rückkehr eine neue Funktion die wird intern die alert Funktion mit dem "click" Argument aufrufen.


Ein ähnlicher Fall ist, wenn Sie setTimeout(() => alert("after 1 second"), 1000) tun. setTimeout erwartet eine Funktion. Wenn Sie setTimeout(alert("..."), 1000) tun, wird die alert in der Tat aufgerufen werden, aber die setTimeout wird als erstes Argument undefined erhalten (das ist, was alert zurückgibt).

Stattdessen, wenn Sie eine Funktion haben, die gibt eine Funktion, wird dies funktionieren:

// This will be called first and will return a function 
const sayHelloTo = name => { 
    // This will be the function passed to `setTimeout` 
    return() => alert(`Hello ${name}`); 
}; 
setTimeout(sayHelloTo("Alice"), 1000); 

Sie es auf die gleiche Art und Weise für das onClick Dingen verwenden:

onClick={sayHelloTo("Alice")} 

Dies ist ein sehr kleines Beispiel, was passiert im Hintergrund (es ist nur ein Beweis für das Konzept, ich bin mir sicher, was es tatsächlich passiert ist viel besser th ein this):

const elm = { 
    onClick: null, 
    // The click method can be invoked manually 
    // using `elm.click()` or is natively invoked by the browser 
    click() { 
    if (typeof this.onClick === "function") { 
     this.onClick(); 
    } 
    } 
}; 

// If you do: 
elm.onClick = alert("click"); // this calls the alert, and returns undefined 
elm.onClick === undefined // true 

// But when doing: 
elm.onClick =() => alert("click"); 
typeof elm.onClick // "function" 

elm.click(); // this will call the alert 
+0

Danke! Ihre Antwort und die von Andrew haben es mir jetzt viel klarer gemacht! – coffeeak

+0

Dies ist eine großartige Antwort, aber wäre besser, wenn es tatsächlich erklärt, warum der Rückgabewert genauer genannt wurde, was das Problem ist. – Li357

+0

@coffeeak Cool! Betrachten Sie eine der Antworten zu markieren :) –

4

Wenn Sie einen Event-Handler haben muss es sich um eine Funktionsreferenz, kein Funktionsaufruf sein. Dies liegt daran, dass intern, wenn der Handler ausgeführt wird, der Handler zuerst ausgewertet wird, bevor er aufgerufen werden kann. Bei Inline-JSX-Ausdrücken, z. B. beim Übergeben einer Ereignishandler-Prop, wird der Ausdruck ausgewertet, wenn die Komponente deklariert wird, bevor der Handler aufgerufen wird.

Wenn Sie also einen Aufruf wie alert('click') übergeben, wird eine Warnung ausgegeben, während sie ausgewertet wird. Wenn das Ereignis ausgelöst wird und der Handler aufgerufen wird, wird es versuchen, den Rückgabewert alert (der nicht definiert ist) aufzurufen - nicht gut. Stattdessen benötigen Sie eine Funktionsreferenz, die Ihnen bei Auswertung eine aufrufbare Funktion gibt, die dann als Handler bezeichnet wird.

dieses Pseudo-Code für ein Beispiel:

function on(event, handler) { 
    //some event listener function that runs the handler when event happens 
    //then we call handler when the event happens: 
    handler(); 
} 

Stellen Sie sich vor, wenn wir die Funktion als on('click', alert('test')) aufgerufen, würde dann alert('test') und der Rückgabewert als Handler weitergegeben würden ausgewertet werden, die nicht definiert ist. Dann würden Sie versuchen, undefined() aufzurufen, nicht gut. Daher müssen Sie eine Funktionsreferenz übergeben, eine Referenz auf eine aufrufbare Funktion.

+0

Danke! Sehr schön erklärt! – coffeeak

Verwandte Themen