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.