Search code examples
javascriptreactjscanvas

unable to get canvas in react element


I'm trying to access a canvas element inside a react component. The canvas is null error is thrown. Tried to initialize canvas with useEffect(), it didn't help. Tell me, please, am I doing something wrong? UPD: instead of createRef() I tried to use useRef(), it also doesn't work :(

My React Component

import {createRef, useRef} from "react";

export default function InteractiveElement() {
    let r = useSelector(state => state.r);
    const imageSizePx = 400;

    const ref = createRef();
    const canvas = ref.current;
    const chart = canvas.getContext('2d');


    canvas.addEventListener('mousedown', (e) => {
        if (e.clientX < imageSizePx / 2 && e.clientY < imageSizePx / 2) {
            const rect = e.target.getBoundingClientRect();
            const x = e.clientX - rect.left; // x position within the element.
            const y = e.clientY - rect.top; // y position within the element.

            console.log("X = ", getXTopLeft(x));
            console.log("Y = ", getYTopLeft(y));
        }
    });

    const getXTopLeft = (px) => {
        return -3 * (1 - px / (imageSizePx / 2));
    }

    const getYTopLeft = (px) => {
        return 3.3 * (1 - px / (imageSizePx / 2));
    }

    return (
        <div className="main__coord">
            <canvas className={"interactive_element"} ref={ref} id={"chart"}/>
            <img src={require("../style/coordinate-form.jpg")} alt={"coordinate-place"}/>
        </div>
    )
}


Solution

    • The useRef hook should be used here instead of createRef.
    • The ref is not initialized during the first render (as React needs to see the returned JSX first); use it in an effect instead.
    const ref = useRef();
    useEffect(() => {
        const canvas = ref.current;
        const chart = canvas.getContext('2d');
        canvas.addEventListener('mousedown', (e) => {
          if (e.clientX < imageSizePx / 2 && e.clientY < imageSizePx / 2) {
              const rect = e.target.getBoundingClientRect();
              const x = e.clientX - rect.left; // x position within the element.
              const y = e.clientY - rect.top; // y position within the element.
    
              console.log("X = ", getXTopLeft(x));
              console.log("Y = ", getYTopLeft(y));
          }
        });
    }, []);