0

I am working through the following code:

class Canvas extends React.Component {
  componentDidMount() {
    const canvas = this.refs.canvas;
    const ctx = canvas.getContext("2d");
    const img = this.refs.image;

    img.onload = () => {
      ctx.drawImage(img, 0, 0);
      ctx.font = "40px Courier";
      ctx.fillText(this.props.text, 210, 75); // THIS IS THE PLACE TEXT IS EMBEDDED INTO THE PICTURE
    };
  }
  render() {
    return (
      <div>
        <canvas ref="canvas" width={640} height={425} />
        <img
          ref="image"
          alt="Stackoverflow56203352"
          src={backImg}
          className="hidden"
        />
      </div>
    );
  }
}

I am trying to convert it to functional form and my effort has been so far stalled due to lack of replacement of getContext.

i.e my try here:

const Canvas = ({}) => {
  const canvas = useRef("")
  const ctx = canvas.getContext("2d")
  const img = useRef("")

  img.onload = () => {
    ctx.drawImage(img, 0, 0);
    ctx.font = "40px Courier";
    ctx.fillText(this.props.text, 210, 75); // THIS IS THE PLACE TEXT IS EMBEDDED INTO THE PICTURE
  };  

  return (
          <div>
            <canvas ref="canvas" width={640} height={425} />
            <img
              ref="image"
              alt="Stackoverflow56203352"
              src={backImg}
              className="hidden"
            />
          </div>
        );

}

doesn't cut it.

The complete sandbox code is at this location

1 Answer 1

3

The main change is that you need to do your wiring up in useEffect, ensuring to use .current to access the current ref for your canvas and image.

Originally I thought it would work with only a single useEffect but it failed on reloading the page (I think due to the image being cached and not triggering onload again). Adding a second useEffect has solved it (thanks to Dennis Vash for the catch):

const Canvas = props => {
  const canvas = useRef(null);

  const image = useRef(null);

  useEffect(() => {
    const ctx = canvas.current.getContext("2d");
    image.current.onload = () => {
      ctx.drawImage(image.current, 0, 0);
      ctx.font = "40px Courier";
      ctx.fillText(props.text, 210, 75);
    };
  }, []);

  useEffect(() => {
    const ctx = canvas.current.getContext("2d");
    ctx.drawImage(image.current, 0, 0);
    ctx.font = "40px Courier";
    ctx.fillText(props.text, 210, 75);
  });

  return (
    <div>
      <canvas ref={canvas} width={640} height={425} />
      <img
        ref={image}
        alt="Stackoverflow56203352"
        src={backImg}
        className="hidden"
      />
    </div>
  );
};

Also, use {} around your refs (not quotes).

Updated sandbox using two useRef hooks here

Sign up to request clarification or add additional context in comments.

6 Comments

Try to refresh the page couple of times
Using your code the text on image vanishes. I have given a sandbox link in the question.
have updated... ideally the rendering code should be moved into a separate useCallback but it's working now.
I added the font rendering back in to the 'onload' of the first useEffect and removed the props.text dependency limitation from the second one.
Thanks!! big help
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.