Michał
Michał

Reputation: 101

when React uses Canvas - drawing

I try to draw with React. Simple onMouseMove event doesnt work. I dont know what I am doing wrong, but it display only first position of state, so rectangle with coordinates 0, 0. Maybe it is concerned with livecycle? Unfortunately There is a lot of stuff about canvas but not with React.

class App extends Component {

 state = { x: 0,
           y: 0
         }

 handleMouseMove(event) {
     this.setState({
       x: event.clientX,
       y: event.clientY
     });
  }


 componentDidMount() {
  const canvas = this.refs.canvas;
  canvas.width = 1000;
  canvas.height = 600;
  const ctx = canvas.getContext("2d");
  ctx.fillRect(this.state.x, this.state.y, 15,15)
 }
 render() {

   return (
     <div>

      <canvas ref="canvas"
        onMouseMove={e=>this.handleMouseMove(e)}>
      and now what!
      </canvas>
     </div>

   );
 };
}

Upvotes: 0

Views: 1802

Answers (1)

Rishul Matta
Rishul Matta

Reputation: 3493

I ll answer this question in parts.

Whats wrong with your implementation?

You are trying to glue state with canvas which is fine. But where are you doing it?

Inside: componentDidMount , From the docs this gets called only once hence you see the initial 0,0 position.

But wait!!! I am updating state and it should update every other thing right?

No! Why?

ctx.fillRect(this.state.x, this.state.y, 15,15) // this place updates the canvas properties

if you observe ctx is actually a plain js reference to the canvas dom element. It is not a react component!

Explain more!

  1. If you wrap canvas inside a component and pass the coordinates as props then things will go fine as react will update the child when the parent's state changes.

Something like this:

const Canvas = (props) =>  <canvas ref="canvas" width={props.x} height={props.y}
        onMouseMove={e=>this.handleMouseMove(e)}>
      and now what!
  </canvas>


class App extends Component {

 state = { x: 0,
           y: 0
         }

 handleMouseMove(event) {
     this.setState({
       x: event.clientX,
       y: event.clientY
     });
  }


 componentDidMount() {
 }
 render() {

   return (
     <div>

      <Canvas x={this.state.x} y={this.state.y} />
     </div>

   );
 };
}

  1. Or a second approach is take care of updating part yourself. i.e. hook into react's update lifecycle, whenever state update happens listen to react's callback (componentDidUpdate) and do the computations yourself.

Working js fiddle: here

Upvotes: 1

Related Questions