Search code examples
javascriptreactjscanvasref

React canvas with ref omitting calling ref.current and ctx?


Is it possible to omit to call

const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');

each time I want to refer to canvas DOM node in a function or useEffect hook?

const drawCanvas = () => {
  const canvasRef = React.useRef(null);
  const [position, setPosition] = React.useState({});

  React.useEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');
    ctx.fillRect(0, 0, canvas.width, canvas.height);
  }, []);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    const x = canvas.width;
    const y = canvas.height;
    setPosition({ x, y });
  }, []);

  return <canvas ref={canvasRef} />;
};


Solution

  • Indeed, you cannot set the current ref node to a variable.

    If you have to implement the same logic in different components, you could create your own hook:

    const useCanvas = (callback) => {
      const canvasRef = React.useRef(null);
    
      React.useEffect(() => {
        const canvas = canvasRef.current;
        const ctx = canvas.getContext('2d');
        callback([canvas, ctx]);
      }, []);
    
      return canvasRef;
    }
    
    const Canvas = () => {
      const [position, setPosition] = React.useState({});
      const canvasRef = useCanvas(([canvas, ctx]) => {
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        const x = canvas.width;
        const y = canvas.height;
        setPosition({ x, y });
      });
    
      return (<canvas ref={canvasRef} />);
    };
    

    A few remarks: