WallEBot
WallEBot

Reputation: 41

React HTML-Canvas issue with setupCanvas() returning TypeError: Undefined

First time using React in this way - trying to draw a basic mock-up canvas to start a new game but returning with 'Uncaught TypeError: Cannot read property 'setupCanvas' of undefined'. Can anyone spot why?

game.jsx

// initial game parameters and setup
'use strict';

import React from 'react';

export default React.createClass({
    propTypes: {
        rectHeight: React.PropTypes.number,
        rectWidth: React.PropTypes.number,
        width: React.PropTypes.number,
        height: React.PropTypes.number
    },
    getDefaultProps() {
        return {
            rectHeight: 300,
            rectWidth: 25,
            width: 800,
            height: 600
        }
    },
    getInitialState() {
        return {

        }
    },
    componentDidMount: () => {
        this.setupCanvas();
        this.draw()
    },
    canvas: undefined,
    context: undefined,
    canvasStyle: {
        margin: 'auto'
    },
    setupCanvas: () => {
        this.canvas = this.getDOMNode();
        this.context = this.canvas.getContext('2d');
    },
    draw() {
        this.context.fillRect(50, 50, this.rectWidth, this.rectHeight);
        this.context.save();
        this.context.fillStyle = 'blue';
    },
    render() {
        return (
            <canvas 
              style={this.canvasStyle}
              width={this.props.width}
              height={this.props.height} />
        )
    }
});

app.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import Game from './components/game';

ReactDOM.render(
    <Game />, document.getElementById('main')
);

index.html

<html>
    <head>
        <meta charset='utf-8'>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Intelligent Mouse</title>
    </head>
    <body>
        <div id='main'></div>
        <script src='bundle.js'></script>
    </body>
</html>

Upvotes: 0

Views: 832

Answers (1)

Andy Noelker
Andy Noelker

Reputation: 11269

By using the arrow function expression, you are lexically binding the this keyword to your function properties. However, because you are defining your functions as properties of your main class, you do not want to do this. Change property values to anonymous functions and it should work.

export default React.createClass({
propTypes: {
    rectHeight: React.PropTypes.number,
    rectWidth: React.PropTypes.number,
    width: React.PropTypes.number,
    height: React.PropTypes.number
},
getDefaultProps: function() {
    return {
        rectHeight: 300,
        rectWidth: 25,
        width: 800,
        height: 600
    }
},
getInitialState: function() {
    return {

    }
},
componentDidMount: function() {
    this.setupCanvas();
    this.draw()
},
canvas: undefined,
context: undefined,
canvasStyle: {
    margin: 'auto'
},
setupCanvas: function() {
    this.canvas = this.getDOMNode();
    this.context = this.canvas.getContext('2d');
},
draw: function() {
    this.context.fillRect(50, 50, this.rectWidth, this.rectHeight);
    this.context.save();
    this.context.fillStyle = 'blue';
},
render: function() {
    return (
        <canvas 
          style={this.canvasStyle}
          width={this.props.width}
          height={this.props.height} />
    )
}
});

Upvotes: 1

Related Questions