什么是 React 16.3 中从 props 更新画布的正确生命周期方法



我有一个 Canvas 组件,它看起来像这样:

class Canvas extends React.Component{
    saveRef = node => {
        this._canvas = node;
    }
    
    shouldComponentUpdate(){
        /*I will never re-render this component*/
        return false;
    }
    
    componentWillReceiveProps( nextProps ){
        /*Here I do manipulations with this._ctx, when new props come*/
    }
    
    render(){
        return (
            <canvas ref={this.saveRef} />
        );
    }
    
    componentDidMount(){
        this._ctx = this._canvas.getContext( "2d" );
    }
}
<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>

React 社区开始弃用 componentWillReceiveProps 以用 getDerivedStateFromProps 替换它。我可以使用componentDidUpdate来执行我的绘图,但是我需要删除shouldComponentUpdate,并且我将有很多无用的渲染调用。当新道具出现时,在 react 16.3 中更新我的组件的正确性能方法是什么?

使用 componentDidUpdate 进行这样的 DOM 操作。对于具有始终具有相同道具的单个子组件的组件,shouldComponentUpdate不会真正产生影响。因此,您应该能够在没有显着性能差异的情况下将其删除。

如果您已经分析了应用程序并确定在此特定情况下它确实有所作为,则可以将元素提升到构造函数中。

这样 React 将完全跳过它(其有效的工作方式与 shouldComponentUpdate 相同(:

class Canvas extends React.Component {
  constructor(props) {
    super(props);
    this._ctx = null;
    this._child = <canvas ref={node => {
      this._ctx = node ? node.getContext('2d') : null
    } />;
  }
  componentDidUpdate(prevProps){
    // Manipulate this._ctx here
  }
  render() {
    // A constant element tells React to never re-render
    return this._child;
  }
}

您也可以将其拆分为两个组件:

class Canvas extends React.Component {
  saveContext = ctx => {
    this._ctx = ctx;
  }
  componentDidUpdate(prevProps){
    // Manipulate this._ctx here
  }
  render() {
    return <PureCanvas contextRef={this.saveContext} />;
  }
}

class PureCanvas extends React.Component {
  shouldComponentUpdate() {
    return false;
  }
  render() {
    return (
      <canvas
        ref={node => node ? this.props.contextRef(node.getContext('2d') : null)}
      />;
  }
}

我发现这是因为我有一个类似的问题,但不完全相同。对我有用的解决方案就是将所有相关代码放在shouldComponentUpdate

(if语句曾经在componentWillReceiveProps(

  shouldComponentUpdate (nextProps, nextState) { // no more random renders
    if (
      (nextProps.nightMode !== this.props.nightMode) ||
      (nextProps.language  !== this.props.language)
    ) {
      this.props.setRefresh(true)                       // setTimeout means after current operation
      setTimeout(() => this.props.setRefresh(false), 1) // so loading will show for longer than 1ms
    }
    return this.props.refresh !== nextProps.refresh
  }

最新更新