Fabric.js with React – cannot change to drawingMode

I’m trying to change some of the fabric.Canvas object properties on button clicks.
When I consol.log properties after change everything seems fine, but it doesn’t have any effect on drawing. Adding objects works but with some unexpected behaviour.

This is the component where I render my canvas:

export const WhiteboardBox: FC<WhiteboardBoxProps> = ({}) => {
  return (
    <div>
      <WhiteboardTools />
      <canvas id="fabricCanvas" />
    </div>
  );
};

It renders WhiteboardTools which should handle drawing, adding objects etc.:


let canvas: Canvas;
export const WhiteboardTools: FC = () => {
  const [color, setColor] = useState("blue");

  useEffect(() => {
    canvas = new fabric.Canvas("fabricCanvas", {
      height: 900,
      width: 1600,
      backgroundColor: "white",
    });

    canvas.isDrawingMode = true;
  }, []);

  useEffect(() => {
    canvas.freeDrawingBrush.color = color;
  }, [color]);

  const testChangeColor = () => {
    setColor((color) => (color === "red" ? "blue" : "red"));
  };

  const testObjectAdd = () => {
    canvas.add(
      new fabric.Rect({
        width: 50,
        height: 50,
        fill: "green",
      })
    );
    canvas.isDrawingMode = false;
    canvas.renderAll();
  };

  const testDrawingOff = () => {
    canvas.isDrawingMode = false;
  };

  const logCanvasProps = () => {
    const { isDrawingMode, freeDrawingBrush } = canvas;
    console.log({ isDrawingMode, freeDrawingBrush });
  };

  return (
    <div className={styles.container}>
      <div>
        <button onClick={testChangeColor}>change color</button>
        <button onClick={testObjectAdd}>Add obj</button>
        <button onClick={testDrawingOff}>Drawing off</button>
        <button onClick={() => logCanvasProps()}>Print</button>
        <>State color: {color}</>
      </div>
    </div>
  );
};

There are two main issues which I cannot solve:

  • changing canvas.isDrawingMode property doesn’t do anything (even though it is changed when I log it).
    Same when I set a color state – useEffect fires, but doesn’t have any effect on actual drawing color,
  • testObjectAdd (the only method which actually changes canvas) spawns rectangle which I want, but all previously drawn stuff disappears. Then, when I draw something, that stuff comes back, but my rectangle disappears…

I’m declaring canvas outside of component because this is what I saw people doing (and working for them).
I also tried with it being a state either insinde WhiteboardBoxor WhiteboardTools with same results.