admin管理员组文章数量:1336631
So I'm trying to modify the state of a ponent which contains a canvas element. The canvas itself should not update since the state affected does not affect the rendering of the 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});
}
ponentDidMount() {
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>
);
}
}
Yet an error shows up when I trigger the event onClick of the canvas :
Uncaught TypeError: Cannot read property 'getContext' of null
at ref (App.js:52)
So I'm trying to modify the state of a ponent which contains a canvas element. The canvas itself should not update since the state affected does not affect the rendering of the 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});
}
ponentDidMount() {
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>
);
}
}
Yet an error shows up when I trigger the event onClick of the canvas :
Uncaught TypeError: Cannot read property 'getContext' of null
at ref (App.js:52)
Share
Improve this question
asked Dec 10, 2017 at 12:37
Sara DoeSara Doe
1451 gold badge2 silver badges9 bronze badges
0
3 Answers
Reset to default 1React ponent will re-render itself on any of its state property change. If you want control on this behavior, consider overriding shouldComponentUpdate
method. If you return false
from this method for any state
condition, your ponent will not re-render for that condition.
Now, regarding the error, you should move the arrow function definition of ref
into a function reference.
The reason is, arrow function will always be passed as new instance while re-rendering, while the function reference will be passed only once during first time render.
Read more from here to know about this in more detail.
Your implementation should be as follows:
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 });
}
ponentDidMount() {
this.ctx.fillRect(50, 50, 100, 100);
}
render() {
return (
<div id="container">
<canvas
width={900}
height={500}
ref={this.setContext}
onClick={() => this.handleClick()} />
/>
</div>
);
}
}
Move the Canvas to it's own class based ponent then use shouldComponentUpdate as mentioned above, if you're rendering Canvas directly in the render method of this ponent it will re-render every time something is changed, but since you need the state to be updated you can not specify which elements need to be re-rendered unless these elements are own ponents and have should ponent update. You can then pass callback functions to get ref and onClick methods.
React docs Refs Caveats explain why you get the getContext() of null
.
If the ref
callback is defined as an inline function, it will get called twice during updates, first with null and then again with the DOM element. This is because a new instance of the function is created with each render, so React needs to clear the old ref and set up the new one. You can avoid this by defining the ref callback as a bound method on the class, but note that it shouldn’t matter in most cases. In your case it matters since you're calling ctx.getContext("2d")
.
For getting rid of unnecessary renders of canvas
, as already mentioned from other answers, encapsulate isPlaying
in a React.PureComponent
and municate changes through an onChange
prop.
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");
}
ponentDidMount() {
this.ctx.fillRect(50, 50, 100, 100);
}
render() {
return (
<canvas
width={900}
height={500}
ref={this.setRef}
onClick={() => this.handleClick()}
/>
);
}
}
本文标签: javascriptUpdating a component including a canvas with ReactStack Overflow
版权声明:本文标题:javascript - Updating a component including a canvas with React - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742412747a2470115.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论