繁体   English   中英

使用React更新包含画布的组件

[英]Updating a component including a canvas with React

因此,我正在尝试修改包含canvas元素的组件的状态。 画布本身不应该更新,因为受影响的状态不会影响画布的渲染?

import React from 'react';

export default class App extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            isPlaying: false
        }
    }

    handleClick() {
        this.setState({isPlaying: true});
    }

    componentDidMount() {
        this.ctx.fillRect(50,50, 100, 100);
    }

    render() {
        return(
            <div id='container'>
                <canvas width={900} height={500}
                    ref={r => this.ctx = r.getContext('2d')}
                    onClick={() => this.handleClick()} />
            </div>
        );
    }
}

当我触发画布的onClick事件时,仍然显示错误:

Uncaught TypeError: Cannot read property 'getContext' of null
at ref (App.js:52)

React组件将在其任何状态属性更改时重新呈现自己。 如果要控制此行为,请考虑重写shouldComponentUpdate方法。 如果您针对任何state条件从此方法返回false ,则组件将不会针对该条件重新呈现。

现在,关于错误,您应该将ref的箭头函数定义移至函数引用中。

原因是,箭头函数在重新渲染时将始终作为新实例传递,而函数引用在首次渲染时将仅传递一次。

此处了解更多信息,以了解更多详细信息。

您的实现应如下所示:

import React from "react";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isPlaying: false
    };
    this.setContext = this.setContext.bind(this);
  }

  setContext(r) {
    console.log(r);
    this.ctx = r.getContext("2d");
  }

  handleClick(e) {
    this.setState({ isPlaying: true });

  }

  componentDidMount() {
    this.ctx.fillRect(50, 50, 100, 100);
  }

  render() {
    return (
      <div id="container">
        <canvas
          width={900}
          height={500}
          ref={this.setContext}
          onClick={() => this.handleClick()} />
        />
      </div>
    );
  }
}

React文档Refs警告说明了为什么获得getContext() of nullgetContext() of null

如果ref回调定义为内联函数,则它将在更新期间被调用两次, 首先是null ,然后是DOM元素。 这是因为每个渲染都会创建该函数的新实例,因此React需要清除旧的ref并设置新的ref。 您可以通过将ref回调定义为类的绑定方法来避免这种情况,但是请注意,在大多数情况下,它无关紧要。 就您而言,这很重要,因为您正在调用ctx.getContext("2d")

为了摆脱不必要呈现的canvas ,因为已经从其他的答案中提到,封装isPlayingReact.PureComponent和交流通过一个变化onChange道具。

import * as React from 'react';

export class Canvas extends React.PureComponent {
  state = {
    isPlaying: false
  }

  handleClick(e) {
    const isPlaying = !this.state.isPlaying;
    this.setState({isPlaying});
    this.props.onChange && this.props.onChange(isPlaying)
  }

  setRef = (ctx) => {
    this.ctx = ctx.getContext("2d");
  }

  componentDidMount() {
    this.ctx.fillRect(50, 50, 100, 100);
  }

  render() {
    return (
     <canvas
        width={900}
        height={500}
        ref={this.setRef}
        onClick={() => this.handleClick()}
      />
    );
  }
}

将Canvas移至其自己的基于类的组件,然后如上所述使用shouldComponentUpdate ,如果直接在此组件的render方法中呈现Canvas,则每次更改某些内容时它都会重新呈现,但是由于您需要更新状态您无法指定需要重新渲染的元素,除非这些元素是自己的组件并且应该更新组件。 然后,您可以传递回调函数以获取ref和onClick方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM