0

I have the following code where the contextRef is not null as expected:

useEffect(() => {
    contextRef.current = canvasRef.current.getContext("2d")
    console.log("In useEffect, contextRef=", contextRef)
}, [])

const onCanvasClicked = () => {
    console.log("DEBUG---- contextRef:", contextRef)
    contextRef.current.drawImage(image, 20, 20)
}

while if add a setImage inside the useEffect then the contextRef printed by the onCanvasClicked becomes null, why?

useEffect(() => {
    contextRef.current = canvasRef.current.getContext("2d")
    console.log("In useEffect, contextRef=", contextRef)
    const myImage = new Image(200,200)
    myImage.src = "https://s-media-cache-ak0.pinimg.com/236x/d7/b3/cf/d7b3cfe04c2dc44400547ea6ef94ba35.jpg"
    setImage(myImage)                // <------------------ the cause
}, [])

const onCanvasClicked = () => {
    console.log("DEBUG---- contextRef:", contextRef) // <----------- becomes null

    contextRef.current.drawImage(image, 20, 20)
}

import {createRef, useEffect, useState} from "react";


const ImageDisplay = () => {
    const [image, setImage] = useState()
    const canvasRef = createRef()
    const contextRef = createRef()

    useEffect(() => {
        contextRef.current = canvasRef.current.getContext("2d")
        console.log("In useEffect, contextRef=", contextRef)
        const myImage = new Image(200,200)
        myImage.src = "https://s-media-cache-ak0.pinimg.com/236x/d7/b3/cf/d7b3cfe04c2dc44400547ea6ef94ba35.jpg"
        setImage(myImage)
    }, [])

    const onCanvasClicked = () => {
        contextRef.current.drawImage(image, 20, 20)
    }

    return <div>
        <canvas
            ref={canvasRef}
            width={640}
            height={425}
            onClick={onCanvasClicked}
        />
    </div>
}

export default ImageDisplay
NeoZoom.lua
  • 2,269
  • 4
  • 30
  • 64

1 Answers1

2

You miss used ref usage in function components, you need to use useRef hook instead, see useRef vs createRef

Also, you don't actually need a state or another ref, you making copies of the same instance which is error prone:

const myImage = new Image(200, 200);
myImage.src =
  "https://s-media-cache-ak0.pinimg.com/236x/d7/b3/cf/d7b3cfe04c2dc44400547ea6ef94ba35.jpg";

const ImageDisplay = () => {
  const canvasRef = useRef();

  const onCanvasClicked = () => {
    canvasRef.current.getContext("2d").current.drawImage(myImage, 20, 20);
  };

  return (
    <div>
      <canvas
        ref={canvasRef}
        width={640}
        height={425}
        onClick={onCanvasClicked}
      />
    </div>
  );
};
Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
  • I just realized that those "tutorial" on YouTube is error-prone. (I mimic the code from a YouTube video, which created two refs.) – NeoZoom.lua Jun 03 '21 at 12:56