I have a handler for a form submit that takes a user image, sends it to the back, does stuff on that image, and gives the modified image back (as a base64) to the front to be displayed.
Sending and receiving the image from the back works fine. But after receiving the image in the front API, I cannot give it to front Component, because the component handler is not waiting for the front API return.
Component that has the form and handler :
function Workshop() {
// Used to store and update the front when data are modified
const [imageUpload, setImageUpload] = useState();
const [imageGenerated, setImageGenerated] = useState();
// Handle the submit of the form
const handleSubmit = event => {
event.preventDefault();
// Append the user image to the formData object
setImageUpload(event.target.files[0]);
const formData = new FormData();
formData.append("file", imageUpload);
// Calls the FrontEnd API with the image to be modified
if(imageUpload) {
const res = frontAPI.callGenerateImage(formData);
console.log("back to front"); // ### THIS IS WHERE IT DOESNT WORK ###
console.log(res); // ### THIS IS WHERE IT DOESNT WORK ###
setImageGenerated(res); // ### THIS IS WHERE IT DOESNT WORK ###
}
};
return (
<>
<div className="workshop">
<form method="post" onSubmit={handleSubmit} encType="multipart/form-data">
<input type="file" name="imageUploader" onChange={handleImagePreview} />
<img alt="preview image" src={imagePreview} />
<button type="submit">Modify Image</button>
</form>
<img alt="generated image" src={"data:image/jpeg;base64," + imageGenerated} />
</div>
</>
);
}
export default Workshop;
FrontEnd API with the fetch :
export function callGenerateImage(formData) {
var base64;
fetch("/generator", {
method: "POST",
body: formData
})
.then(data => data.json())
.then(res => {
base64 = Buffer.from(res.data, "binary" ).toString("base64");
console.log(base64); // THIS IS THE BASE64 STRING IN THE OUPUT BELOW
return base64;
})
};
Output :
So as you can see, I do receive the base64 stream of my modified image, but the line const res = fontAPI.callGenerateImage(formData);
doesn't wait for the actual return of the fetch and goes on with the console.log("back to front");
.
I tried to switch my API function to an async function and change
const res = frontAPI.callGenerateImage(formData);
to
const res = await frontAPI.callGenerateImage(formData);
But it doesn't work because I'm not at top level, even if I remove the "if", as I am in a function of the component.
I'm fairly sure that the answer is pretty simple but I don't see it.
Thanks a lot for your help !
EDIT : PROBLEM SOLVED, SEE MY ANSWER BELOW
I got it to work thanks to jbcortez89 and lo-fi wi-fi.
I needed to fix 2 things in my code :
A) Switching the handler to an async function, which I didn't even know was possible this way, which somehow allows me to use await even if I'm not at top level :
const handleSubmit = async (event) => {
event.preventDefault()
if (imageUpload) {
const formData = new FormData();
formData.append("file", imageUpload);
const res = await frontAPI.callGenerateImage(formData);
setImageGenerated(res);
}
B) Fix my API fetch return value. I decided to switch to the new format which is much clearer than the nested then().
export async function callGenerateImage(formData) {
let myData = await fetch("/generator", {
method: "POST",
body: formData
})
let dataJSON = await myData.json();
return Buffer.from(dataJSON.data, "binary" ).toString("base64");
};
thanks a lot guys for your help !