'Screenshot created by use-react-screenshot is not assigning to useState
I am trying to send a screenshot of a certain <div> along with other data in a useState. Screenshot part working fine as I view it at the end of the page. The problem is that it is not assigning to the useState where other data is stored. If I clicked save, the first time it will save the other data without the Screenshot. If I keep clicking Save couple more times, it will eventually save the data with the screenshot. Here is the code,
const [image, takeScreenShot] = useScreenshot();
function getImage(){
takeScreenShot(ref.current)
}
let file = {image};
const [customcard, setCustomcard] = useState({
customcardText1: "",
customcardText2: "",
customcardText3: "",
customcardText4: "",
customcardText5: "",
customcardText6: "",
customcardText7: "",
images: "",
});
function addCustomCardDetails() {
getImage();
console.log(file.image)
setCustomcard({
...customcard,
images: file.image,
})
console.log("saved image:",customcard.images)
if(customcard.images !== null){
axios
.post("http://localhost:2002/customcard/customize-card", customcard)
.then((response) => {
console.log("after axios");
console.log(customcard);
})
.catch((error) => {
console.log(error.message);
alert(error.message);
});
}else
{
alert("Please upload an image");
}
}
other fields of the customercard is set in the form in OnInput.
Solution 1:[1]
You are going against a convention of setting state using previous state. There is another method that is preferred that makes use of a callback function that receives an argument that is the previous state:
setCustomCard((prev) => {...prev, images: file.images})
In another section you are setting your screen shot to a local variable. This variable will get deleted or become stale depending on the behavior of your component. Why use it at all?
I can't be sure the order of operations for your app, but I would suggest something like this:
const [image, takeScreenShot] = useScreenshot();
const [customcard, setCustomcard] = useState({
customcardText1: "",
customcardText2: "",
customcardText3: "",
customcardText4: "",
customcardText5: "",
customcardText6: "",
customcardText7: "",
images: "",
});
function getImage() {
takeScreenShot(ref.current)
}
useEffect(() => {
setCustomCard(prev => {...prev, images: image})
}, [image])
useEffect(() => {
if (customCard.images !== null) {
axios
.post("http://localhost:2002/customcard/customize-card", customcard)
.then((response) => {
console.log("after axios");
console.log(customcard);
})
.catch((error) => {
console.log(error.message);
alert(error.message);
});
}
}
}, [customCard])
And for your onInput function, make sure you are using the syntax I show for updating state using previous state something like this:
function onInput(e) {
setCustomCard(prev => {...prev, [e.target.name]: e.target.value})
}
Call getImage from whichever event would be calling addCustomCardDetails instead of trying to set state and use it in the same function. This will cause you to be one render behind, or be referencing a stale file variable.
The useEffect hook will keep track of the changes to your image, or your customCard, and update your state accordingly. Notice the dependency array at the end, that is what is listening for changes.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
