[英]How to pass arguments to callback in React + Typescript without new function creation?
假設您有以下TSX代碼:
render() {
const someParameter = 5;
return (
<div onClick={() => this.doSomething(someParameter)}></div>
);
}
現在,我們知道我們不應該將像這樣的粗箭頭函數傳遞給onClick處理程序,因為它每次都會創建一個新函數,強制重新渲染(這在將回調傳遞給深層組件而不是傳遞函數時尤其糟糕。只是一個div)。
那么接下來的解決辦法,如果沒有參數,將結合doSomething
到this
在我們的類的構造函數,像this.doSomething = this.doSomething.bind(this)
,然后通過綁定功能回調。 但是,在我們的情況下,這並不能解決問題,因為我們想將參數傳遞給函數someParameter。 想象一下,someParameter不僅像上面那樣是一個愚蠢的常量,而是一個數組中的元素,我們通過render()方法在數組中獲得map()。 我們如何處理這種情況? 也就是說,我們如何每次都傳遞一個並非從頭開始創建的函數,從而破壞了僅在必要時智能地重新呈現的功能?
謝謝!
bind
不僅可以綁定上下文,還可以綁定參數。 因此,您可以在構造函數中執行以下操作:
this.doSomething = this.doSomething.bind(this, someArgument)
只有在組件生命周期中someArgument
不變的情況下,以上解決方案才someArgument
。
如果此參數是動態的,唯一的解決方案是像您的示例中那樣使用箭頭函數-但請注意,僅當將此函數作為道具傳遞給子組件(而不是HTML元素)時,才可能需要進行其他重新渲染。 根據反應文檔:
在大多數情況下,這很好。 但是,如果將此回調作為對較低組件的支持傳遞,則這些組件可能會進行額外的重新渲染。
如果您不將其傳遞給React子組件,那應該不是問題,也不會引起任何其他的重新渲染。 請注意,React組件和HTML標簽之間存在區別。 如果將箭頭函數用作HTML元素上的事件回調(例如,在地圖中生成的div上),則它不會觸發此div
其他呈現,因為它不是組件,並且沒有render方法。 React Virtual DOM算法將決定是否應更新與此div
對應的實際DOM元素,而在我們這種情況下,將不更新現有DOM元素(您可以使用dev工具進行檢查)。
class Hello extends React.Component{ constructor() { super(); this.state = {test: 0}; } componentDidMount() { var i =0; this.timer = setInterval(() => { i++; this.setState({test: i}) }, 1000) } componentWillUnmount() { clearInterval(this.timer) } render() { return (<div>{this.state.test} { [1, 4, 6].map((v) => { return (<div key={v} onClick={() => { console.log(this.state.test)}}>test</div>) }) } </div>); } }; ReactDOM.render( <Hello name="World" />, document.getElementById('container') );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="container"> <!-- This element's contents will be replaced with your component. --> </div>
您可以檢查上述代碼段生成的輸出,以查看div
元素是否在DOM中未更新,盡管它們已將箭頭功能定義為事件回調,並將其父組件重新呈現。
如果您需要將此函數傳遞給子組件,可以分別傳遞帶函數的prop和帶參數值的prop以避免極端的重新渲染(當然,您還必須實現shouldComponentUpdate
):
<SomeComponent myClick={this.doSomething} myArgument={someArgument} />
在SomeComponent的某處:
//JSX in SomeComponent render method
<div onClick={() => this.props.myClick(this.props.myArgument)} >...</div>
您也可以在SomeComponent中創建其他方法,而不是使用箭頭函數:
handleMyClick() {
this.props.myClick(this.props.myArgument);
}
然后使用JSX:
<div onClick={this.handleMyClick} >...</div>
綜上所述:如果將箭頭函數用作HTML標記上的事件回調,則不會造成性能問題,也不會觸發任何其他重新渲染-僅在必要時,它不會破壞智能重新渲染的能力。 僅當將箭頭功能作為道具傳遞給子組件時,才可能導致其他重新渲染,在這種情況下,您可以使用我建議的解決方案。
您能否檢查“建議”部分中此處提出的解決方案? https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md
看起來這可能可行:
var List = createReactClass({
render() {
return (
<ul>
{this.props.items.map(item =>
<ListItem key={item.id} item={item} onItemClick={this.props.onItemClick} />
)}
</ul>
);
}
});
var ListItem = createReactClass({
render() {
return (
<li onClick={this._onClick}>
...
</li>
);
},
_onClick() {
this.props.onItemClick(this.props.item.id);
}
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.