For context, I’m trying to make a project using the html canvas in React. I am trying to replace the class components with functional components for uniformity and avoiding mixing of class and functional components. The example below should simply move a blue rectangle from left to right.
I am convinced the file paths are correct, and my canvas and context variables are correctly initialised (code provided a bit later). However I’m a bit lost on how to proceed refactoring the code to make it behave the same as the class component.
This is the actual class and its usage (in vanilla javascript):
class Bar {
constructor(x, y, width, height, color) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
}
update(){
this.x++;
}
draw(context){
context.fillStyle = this.color;
context.fillRect(this.x, this.y, this.width, this.height);
}
}
Usage:
const bar1 = new Bar(10, 10, 100, 200, "blue");
function animate(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
bar1.draw(ctx);
requestAnimationFrame(animate);
}
animate();
This is my attempt at mimicking the functionality. First, the Bar functional component:
import React, {useState} from 'react';
const Bar = ({initialX, initialY, initialWidth, initialHeight, initialColor}) => {
const [x, setX] = useState(initialX);
const [y, setY] = useState(initialY);
const [width, setWidth] = useState(initialWidth);
const [height, setHeight] = useState(initialHeight);
const [color, setColor] = useState(initialColor);
const update = () => {
const newX = x + 1;
setX(newX);
}
const draw = (context) => {
context.fillStyle = color;
context.fillRect(x, y, width, height);
}
return (
<div>
</div>
);
};
export default Bar;
And this is where the Bar component should be used, but I’m somewhat lost on how to "use" it. Do I just use it as a function? Render it as <Bar/>
and provide props? Assign <Bar/>
to a variable bar and use the draw()
function from that?
import Bar from "../components/Bar.jsx";
const Visualiser = () => {
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const animate = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
requestAnimationFrame(animate);
}
animate();
};
export default Visualiser;
Would appreciate any guidance on how to go about this!
2
Answers
To render to the canvas you need an actual canvas element, which I’m not seeing in your
Bar
component. In a functional component you can use useRef to create a reference to the canvas, and then start the animation loop in a useEffect.If you want to just use it as function you can have it return the draw and update methods.
in parent it would pretty much be the same code you used in class based example.