簡體   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