简体   繁体   中英

Declared const variable not visible in useEffect

I am working through the following code:

index.js

import React, {useRef, useState, useEffect} from "react";
import ReactDOM from "react-dom";
import AddAPhotoTwoTone from '@material-ui/icons/AddAPhotoTwoTone'
import backImg from "./background.png";

const Canvas = (props) => {
  const canvas = useRef(null);
  const image = useRef(null);
  const xLoc = useState(props.backImg.width/2)
  const yLocTop = useState(props.backImg.height/2)
  const yLocBottom = useState(props.backImg.height/2)

  useEffect(() => {
    const ctx = canvas.current.getContext("2d");
    image.current.onload = () => {
      ctx.drawImage(image.current, 0, 0);            
      ctx.font = "20px Courier";
      ctx.textAlign = "center";
      console.log(xLoc)
      ctx.fillText(props.textTop, xLoc, yLocTop);
      ctx.textAlign = "center";
      ctx.fillText(props.textBottom, xLoc, yLocBottom);
    };
  });

  useEffect(() => {
    const ctx = canvas.current.getContext("2d");
    ctx.drawImage(image.current, 0, 0);
    // const xLoc = canvas.current.width/2
    // const yLocTop = canvas.current.height*.95
    // const yLocBottom = canvas.current.height*0.05
    ctx.font = "20px Courier";
      ctx.textAlign = "center";
      ctx.fillText(props.textTop, xLoc, yLocTop);
      ctx.textAlign = "center";
      ctx.fillText(props.textBottom, xLoc, yLocBottom);
  });

  return (
    <div>
      <canvas ref={canvas} width={props.backImg.width} height={props.backImg.height} />
      <img ref={image} src={props.backImg} hidden/>
    </div>
  );
};


function App() {  
  return (
    <div className="App">  
      <Canvas textTop="TEST 123" textBottom="TEST 456" backImg={backImg} />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Why is the console.log(xLoc) within first useEffect printing NaN ?

  useEffect(() => {
    const ctx = canvas.current.getContext("2d");
    image.current.onload = () => {
      ctx.drawImage(image.current, 0, 0);            
      ctx.font = "20px Courier";
      ctx.textAlign = "center";
      console.log(xLoc)
      ctx.fillText(props.textTop, xLoc, yLocTop);
      ctx.textAlign = "center";
      ctx.fillText(props.textBottom, xLoc, yLocBottom);
    };
  });

Sandbox code is here

Edit:

Even with properly configured useState , it returns NaN on console.

useState() returns an array. The first element is the state-value and the second is its state-updating function. You need to destructure the output like so.

Needs to be

const [xLoc, setxLoc] = useState(props.backImg.width/2)
const [yLocTop, setyLocTop] = useState(props.backImg.height/2)
const [yLocBottom, setyLocBottom] = useState(props.backImg.height/2)

Thus whatever you pass in to useState() will be the initial value.

Additionally. The problem is that the props.backImg is simply a string. It does not have any object properties like .width , and .height . To actually have access to those values, you need to first use that image as a src inside an img tag.

Then the img tag has access to the onLoad event-listener. With an event-handler, we can access the object properties mentioned. In sense, we first need to render the image on the screen, but that doesn't happen until we render the Canvas component, so there is no need to pass in those props from App. See sandbox for more details.

See sandbox: https://codesandbox.io/s/hardcore-night-djzmr

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM