I have a React form with a file as an input, and the onFileChange
saves setFile(e.target.files[0])
(and also toggle a boolean change
). Then when I submit the form:
url
and public_id
I'm looking for)url
and 'public_id
) to the formdata to post to the database backend.I thought that chaining promises should do the job, but I can't achieve it.
Inside my onFormSubmit
, I first define a promise that captures the none async data:
function init(fd){
fd.append('input1'...)
return Promise.resolve(fd)
}
so I can reuse the formdata to feed the next promise upLoadToCL
that should 'normally' asynchronously append the response object from the cloud to the formdata, with:
init(new FormData).then(res => upLoadToCL(res)).then(res=> ...)
function upLoadToCL(fd) {
if (changed) {
// send 'file' (saved as state variable after input) to the cloud
const newfd = new FormData();
newfd.append("file", file);
newfd.append("upload_preset", "ml_default");
fetch(`https://api.cloudinary.com/v1_1/${cloudName}/upload`, {
method: "POST",
body: newfd,
})
.then((res) => res.json())
// append the formdata argument 'fd' with the result
.then((res) => {
setPhoto(res);
fd.append("event[directCLUrl]", res.url);
fd.append("event[publicID]", res.public_id);
})
.catch((err) => {
throw new Error(err);
});
return Promise.resolve(fd);
}
}
I checked that the first promise works and sends to the second promise a 'prefilled' formdata. Then the post request works, and returns a response as I can see that the state variable photo
is updated some time in the futur. However, the promise itself returns a void formdata, even without chaining:
upLoadToCL(new FormData())
.then(res=> {
for (let [k,v] of res){
console.log(k,v)
}
})
returns nothing.
You're already doing the promise chaining fine. You just need to return the result of that promise chain instead of the Promise.resolve(fd)
from your function:
function upLoadToCL(fd) {
if (changed) {
// send 'file' (saved as state variable after input) to the cloud
const newfd = new FormData();
newfd.append("file", file);
newfd.append("upload_preset", "ml_default");
return fetch(`https://api.cloudinary.com/v1_1/${cloudName}/upload`, {
// ^^^^^^
method: "POST",
body: newfd,
})
.then((res) => res.json())
.then((res) => {
setPhoto(res);
// append the formdata argument 'fd' with the result
fd.append("event[directCLUrl]", res.url);
fd.append("event[publicID]", res.public_id);
return fd;
// ^^^^^^ fulfilling the promise with the updated fd
});
} else {
return Promise.resolve(fd);
// ^^^^^^ always returning a promise for fd from uploadToCL()
}
}