VD26
VD26

Reputation: 138

Why getContext function cannot be called on React JSX <canvas> object?

I have the following code in a React.Component subclass

class SearchObject extends React.Component { 

    constructor(props) {
        super(props)

        var activateCanvas = <canvas></canvas>

        var activateDraw = () => {
            let ctx = activateCanvas.getContext('2d')
            //draw stuff
        }

        activateDraw()

        this.state = {
            activate: activateCanvas
        }
    }
...

the activateCanvas.getContext('2d') line returned error, saying getContext is not a function. I wonder why activateCanvas here is not an Element object. Do I have to wait until the element is rendered and call something like document.getElementById() to use getContext()? Thanks

Upvotes: 1

Views: 2136

Answers (2)

Christian Fritz
Christian Fritz

Reputation: 21364

Yes, you need to render the react element you created first. Only then you can start referring to its DOM element. I would recommend using ref for that. Something like this should work:

function App() {

  let ctx;
  var activateDraw = (ref) => {
    console.log('this is the canvas DOM element you want', ref)
    ctx = ref.getContext('2d')
    // draw stuff
  }
  var activateCanvas = (<canvas ref={(e) => activateDraw(e)}></canvas>)

  return (
    <div className="App">
      { activateCanvas /* don't forget to put the element into your render */}
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
         ....

Upvotes: 3

gabriel.hayes
gabriel.hayes

Reputation: 2313

JSX doesn't actually return an HTMLElement it returns a render function, so you're basically trying to do this:

const canvas = function(props, createElement) { /* render canvas*/}; // forgot the ordering of renderFn args... sue me
canvas.getContext('2d');

Personally, I use JSX with Vue, and in the case of Vue, if you wanted to do something like this, the short answer is yes, you would have to wait until it is rendered and then use the DOM to get access to the HTMLElement created by the JSX render function.

Hopefully someone with React expertise can confirm this is the case or provide a more refined answer tailored to your specific use-case with React.

Upvotes: 1

Related Questions