Reputation: 2017
I have a uploadImage function:
const [profileURL, setProfileURL] = useState("")
uploadImage = async (uri, userUID) => {
const response = await fetch(uri)
const blob = await response.blob()
var ref = firebase.storage().ref().child("avatar/" + userUID)
await ref.put(blob, {contentType:'image/jpg'}).catch((error) => {
console.log(error);
})
await ref.getDownloadURL().then((url) => {
setProfileURL(url)
})
}
The upload part is working, the image is saved to firebase storage correctly, But Im trying to get the downloadURL of the image and set it in state setProfileURL({ uri: url})
I then call a handleSubmit function which calls this upload function:
const handleSubmit = async () => {
await this.uploadImage(imageOne, firebase.auth().currentUser?.uid).then(
setCurrentUserDetails(
{ ...currentUserDetails,
name,
age: Number(age),
height,
profileURL,
}
)
);
}
Everything else is updated but this profileURL field doesn't get updated. When I log the state variable on the uploadImage function I get the following:
setProfileURL in upload function [Function bound dispatchAction]
profileURL in upload function
Ii have tried setProfileURL(String(url))
But can't get this DonwnloadURL to save.
I also tried:
uploadImage = async (uri, userUID) => {
const response = await fetch(uri)
const blob = await response.blob()
var ref = firebase.storage().ref().child("avatar/" + userUID)
await ref.put(blob, {contentType:'image/jpg'}).catch((error) => {
console.log(error);
})
const url = await ref.getDownloadURL().catch((error) => {
console.log(error);
})
console.log("URL", url);
setProfileURL(String(url))
return url
}
which does log out the correct url:
URL https://firebasestorage.googleapis.com/MY_URL_HERE
just doesn't seem to update the state?
Upvotes: 0
Views: 206
Reputation: 6652
State updates are not synchronous. From the documentation
setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall. Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied. If you need to set the state based on the previous state, read about the updater argument below.
So by the time setCurrentUserDetails
, profileURL
is not updated. The second approach should work for getting the correct URL. But instead of using profileURL
, you can use the returned url value directly from the method.
const handleSubmit = async () => {
const url = await this.uploadImage(
imageOne,
firebase.auth().currentUser?.uid
);
setCurrentUserDetails({
...currentUserDetails,
name,
age: Number(age),
height,
profileURL: url,
});
};
Upvotes: 1