[英]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.