簡體   English   中英

防止不必要地重新渲染React組件

[英]Prevent unnecessary re-render of React component

我有一個PureComponent可以渲染另一個組件並實現其onClick回調:

class ColorPicker extends React.PureComponent {
  render() {
    console.log('ColorPicker being rendered');
    const fields = this.props.colors.map((color, idx) => {
      const fieldProps = {
        key: `${idx}`,
        color,
        /*onClick: () => { // PROBLEM HERE
          this.props.colorPicked(color);
        }*/
      };
      return <ColorField { ...fieldProps}/>;
    });
    return (
      <div className="bla-picker">
        <div>{`Refresh seed: ${this.props.seed}`}</div>
        {fields}
      < /div>
    );
  }
}

此組件有一個小問題:每當重新渲染ColorPicker ,嵌套的ColorField需要重新渲染,因為它們的onClick屬性每次都會更改。 每當渲染組件時,使用lambda函數將創建該函數的新實例。

我通常通過將onClick的實現移到render方法之外來解決此問題,例如: onClick: this.handleClick 但是,我無法在此執行此操作,因為onClick處理程序需要捕獲color變量。

解決此類問題的最佳實踐是什么?

這是一個jsfiddle進行嘗試; 並作為摘要:

 class ColorField extends React.PureComponent { render() { console.log('ColorField being rendered'); const divProps = { className: 'bla-field', style: { backgroundColor: this.props.color }, onClick: this.props.onClick }; return <div { ...divProps}/>; } } class ColorPicker extends React.PureComponent { render() { console.log('ColorPicker being rendered'); const fields = this.props.colors.map((color, idx) => { const fieldProps = { key: `${idx}`, color, /*onClick: () => { // PROBLEM HERE this.props.colorPicked(color); }*/ }; return <ColorField { ...fieldProps}/>; }); return ( <div className="bla-picker"> <div>{`Refresh seed: ${this.props.seed}`}</div> {fields} < /div> ); } } class Layout extends React.PureComponent { constructor(props, ctx) { super(props, ctx); this.state = { seed: 1 }; } render() { const pickerProps = { colors: ['#f00', '#0f0', '#00f'], colorPicked: (color) => { console.log(`Color picked: ${color}`); }, seed: this.state.seed }; return ( <div> <div className="bla-button" onClick = {this.btnClicked} > {'Click Me'} </div> <ColorPicker { ...pickerProps} /> </div> ); } btnClicked = () => { this.setState({ seed: this.state.seed + 1 }); }; }; ReactDOM.render( < Layout / > , document.getElementById("react") ); 
 .bla-button { background-color: #aaa; padding: 8px; margin-bottom: 8px; } .bla-picker {} .bla-field { width: 32px; height: 32px; } 
 <div id="react"> </div> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> 

只要onClick仍處於注釋狀態,則種子更改時僅重新渲染ColorPicker (請參閱console.log輸出)。 放入onClick之后,所有ColorField也會重新渲染。

您可以在ColorField組件中實現shouldComponentUpdate ,例如:

class ColorField extends React.Component {
  shouldComponentUpdate(nextProps) {
    return this.props.color !== nextProps.color;
  }

  render(){
    const { color, onClick } = this.props;
    console.log('Color re-rendered');
    return (
      <div 
        className="color"
        onClick={onClick}
        style={{ 
          backgroundColor: color,
          height: '50px',
          width: '50px',
        }} 
      />
    )
  }
}

這里的例子

請注意,在第一個解決方案中,我們只能使用React.Component,因為我們自己實現了shouldComponentUpdate

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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