[英]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 null
的getContext() of null
。
如果ref
回调定义为内联函数,则它将在更新期间被调用两次, 首先是null ,然后是DOM元素。 这是因为每个渲染都会创建该函数的新实例,因此React需要清除旧的ref并设置新的ref。 您可以通过将ref回调定义为类的绑定方法来避免这种情况,但是请注意,在大多数情况下,它无关紧要。 就您而言,这很重要,因为您正在调用ctx.getContext("2d")
。
为了摆脱不必要呈现的canvas
,因为已经从其他的答案中提到,封装isPlaying
在React.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.