I am building an whiteboard application and to create the white board I was playing with html canvas element. I was trying to print a word on canvas but I really don't understand why but it is putting it twice on the screen `
import React, { useEffect, useRef } from "react";
const WhiteBoard = () => {
const canvasid = useRef();
useEffect(() => {
const canvas = canvasid.current;
const ctx = canvas.getContext("2d");
ctx.font = "30px Impact";
ctx.rotate(0.1);
ctx.fillText("Awesome!", 50, 100);
// Draw line under text
var text = ctx.measureText("Awesome!");
ctx.strokeStyle = "rgba(0,0,0,0.5)";
ctx.beginPath();
ctx.lineTo(50, 102);
ctx.lineTo(50 + text.width, 102);
ctx.stroke();
}, []);
return (
<>
<div>WhiteBoard</div>
<canvas ref={canvasid} style={{ border: "1px solid red" }}></canvas>
</>
);
};
export default WhiteBoard;
`
I was expecting the code to print Awesome on the canvas once but It is being printed twice, I tested with debugger and It shows that useEffect is being run twice But I only want it to run once when it is mounted on the screen
Even though OP already solved his issue with my comment above, but removing StrictMode
is actually not a good solution here.
Quoting from the React official docs:
We recommend wrapping your entire app in Strict Mode, especially for newly created apps. If you use a framework that calls
createRoot
for you, check its documentation for how to enable Strict Mode.
So, what's the good solution other than removing StrictMode
?
Well, you can use cleanup function for that.
So given the OP question, the answer would be like:
import React, { useEffect, useRef } from "react";
const WhiteBoard = () => {
const canvasid = useRef();
useEffect(() => {
const canvas = canvasid.current;
const ctx = canvas.getContext("2d");
ctx.font = "30px Impact";
ctx.rotate(0.1);
ctx.fillText("Awesome!", 50, 100);
// Draw line under text
var text = ctx.measureText("Awesome!");
ctx.strokeStyle = "rgba(0,0,0,0.5)";
ctx.beginPath();
ctx.lineTo(50, 102);
ctx.lineTo(50 + text.width, 102);
ctx.stroke();
// add this
return () => {ctx.reset()}
}, []);
return (
<>
<div>WhiteBoard</div>
<canvas ref={canvasid} style={{ border: "1px solid red" }}></canvas>
</>
);
};
export default WhiteBoard;
Although i didn't test the code, it should be clear that cleanup function will fix the rendering twice issue.