skip to Main Content

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

3

Answers


  1. Chosen as BEST ANSWER

    React is in strict mode so it re-rendered the Component Twice. Removing React.StrictMode from index.js file fixed the issue


  2. You can refer to this answer. Maybe it’s because of StrictMode.

    https://stackoverflow.com/a/71982736/9546759

    Login or Signup to reply.
  3. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search