簡體   English   中英

如何在不創建新函數的情況下將參數傳遞給React + Typescript中的回調?

[英]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)。

那么接下來的解決辦法,如果沒有參數,將結合doSomethingthis在我們的類的構造函數,像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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM