2017-06-05 60 views
4

React tutorial,它說爲什麼事件處理程序需要引用而不是調用?

onClick={alert('click')}會立即發出警告,而不是在單擊按鈕時。

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

不過,我不明白爲什麼那會是......任何人都可以澄清這對我好嗎?爲什麼不能作爲處理程序傳遞函數調用?

+0

'alert('click')'是一個函數調用。 React會讀取它並立即執行它。您應該將引用傳遞給命名函數。所以,'this.myFunction'而不是'this.myFunction()'。或者,您可以引用一個匿名函數,這就是您在原始文章中輸入的內容。 – glhrmv

回答

9

當你做onClick={alert("click")}這將調用alert函數並將返回值(undefined)分配給onClick屬性。所以,React看到的是onClick={undefined}並說:好吧,那不是一個函數,爲什麼我會添加這樣一個處理程序?

想要傳遞給onClick的是函數,而不是undefined

因此,你必須做的:onClick={myFunction}其中myFunction可以() => alert("...")正如你所說,或者您可以使用bind創建類似的功能:

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

bind一個新功能這將使用"click"參數在內部調用alert函數。


類似的情況是當你做setTimeout(() => alert("after 1 second"), 1000)setTimeout需要一個功能。如果你做setTimeout(alert("..."), 1000),確實會調用alert,但setTimeout將接收第一個參數undefined(這就是alert返回的結果)。

相反,如果你有返回功能,功能,將工作:

// 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); 

您可以使用它以同樣的方式爲onClick啄:

onClick={sayHelloTo("Alice")} 

這是關於背景中發生的事情的一個非常小的例子(這只是一個概念證明,我確定它實際上發生的是更好的方式這一個):

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

謝謝!你的回答和安德魯的回答讓我更清楚了! – coffeeak

+0

這是一個很好的答案,但如果它真的解釋了爲什麼返回值被更詳細地調用,這將是更好的選擇,這是手頭的問題。 – Li357

+0

@coffeeak酷!考慮標記其中一個答案:) –

4

當你有一個事件處理程序它必須是一個函數引用,而不是一個函數調用。這是因爲在執行處理程序的內部,處理程序在被調用之前首先被評估爲。使用內聯JSX表達式(例如傳遞事件處理程序prop時),在調用處理函數之前聲明組件時,表達式爲評估爲

因此,如果您傳入諸如alert('click')之類的調用,它將在進行評估時發出警報。當事件被觸發並且處理程序被調用時,它將嘗試調用返回值alert(這是未定義的) - 不好。相反,你需要一個函數引用,當它被評估時給你一個可調用的函數,然後調用它作爲處理函數。

拿這個僞代碼爲例:

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

試想一下,如果我們調用的功能on('click', alert('test')),然後alert('test')會進行評估和返回值將作爲處理函數,這是不確定的傳遞。那麼你會試圖撥打undefined(),不好。因此,您必須傳遞函數引用,即對可調用函數的引用。

+0

謝謝!非常好的解釋! – coffeeak

相關問題