Warm tip: This article is reproduced from stackoverflow.com, please click
reactjs

ReactJS changing class to functional code

发布于 2020-03-27 10:29:09

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

Questioner
Zanam
Viewed
17
Will Jenkins 2019-07-04 01:06

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