Javascript 在React 16.3中,从道具更新画布的正确生命周期方法是什么?

Javascript 在React 16.3中,从道具更新画布的正确生命周期方法是什么?,javascript,reactjs,canvas,lifecycle,Javascript,Reactjs,Canvas,Lifecycle,我有一个画布组件,大致如下所示: 类画布扩展React.Component{ saveRef=node=>{ 这个.\u canvas=node; } shouldComponentUpdate(){ /*我永远不会重新渲染此组件*/ 返回false; } 组件将接收道具(下一步){ /*这里我用这个做操作。_ctx,当新道具出现时*/ } render(){ 返回( ); } componentDidMount(){ this._ctx=this._canvas.getContext(“2d

我有一个画布组件,大致如下所示:

类画布扩展React.Component{
saveRef=node=>{
这个.\u canvas=node;
}
shouldComponentUpdate(){
/*我永远不会重新渲染此组件*/
返回false;
}
组件将接收道具(下一步){
/*这里我用这个做操作。_ctx,当新道具出现时*/
}
render(){
返回(
);
}
componentDidMount(){
this._ctx=this._canvas.getContext(“2d”);
}
}

对于这样的DOM操作,请使用
componentdiddupdate
。一个
shouldComponentUpdate
对于一个只有一个子组件的组件来说并没有什么区别,因为它总是拥有相同的道具。因此,您应该能够在性能没有显著差异的情况下删除它

如果您已经分析了应用程序,并确定在这种特殊情况下它确实会产生影响,那么您可以将元素提升到构造函数中

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

类画布扩展React.Component{
建造师(道具){
超级(道具);
此参数为.\u ctx=null;
这个.\u child={
此._ctx=node?node.getContext('2d'):null
} />;
}
componentDidUpdate(prevProps){
//操纵这个
}
render(){
//常量元素告诉React永不重新渲染
把这个还给孩子;
}
}
您还可以将其拆分为两个组件:

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)}
      />;
  }
}
类画布扩展React.Component{
saveContext=ctx=>{
这个._ctx=ctx;
}
componentDidUpdate(prevProps){
//操纵这个
}
render(){
返回;
}
}
类PureCanvas扩展了React.Component{
shouldComponentUpdate(){
返回false;
}
render(){
返回(
node?this.props.contextRef(node.getContext('2d'):null)}
/>;
}
}

我发现这一点是因为我遇到了类似的问题,但并非完全相同。对我来说,解决方案就是将所有相关代码放入
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;
  }
}
(以前在
组件中使用的
if
语句将接收props


Can
Canvas
component提供了一些方法来处理要绘制的作业,并且知道何时应该更新的是它的父组件。因此,在父组件调用它之前,
Canvas
组件永远不会更新。这对您有用吗?是的,这是选项之一,但它有两个缺点:第一,如果Canvas组件连接到redux,它取决于存储更新,而不是父级,其次,您应该将更新逻辑移动到其他组件。有没有方法在不重新渲染组件的情况下处理新道具?这种情况可能不仅发生在canvas元素上。例如,您的组件渲染6个容器,这些容器连接到redux。在这种情况下,组件也不会“我不需要重新渲染。@AlexFomin我想添加以下两点:渲染方法中的箭头函数将在每次渲染时创建(导致性能下降)。但是这里的渲染方法中的箭头函数是可以的,因为该组件永远不会更新。此外。getContext()返回一个上下文或null。如果您以前请求过不同的上下文,它可能会返回null。通常您必须检查null,但在这里它不是真正需要的,因为PureCanvas提供了相同的上下文(在这个实现中,您不能请求另一个上下文)。
  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
  }