Reputation: 2015
In my app, when user changes image, the url of the image remains the same, but the image in the cloud changes.
In other words, suppose the url of the image is URL1, after the user uploads his image, the image retrieved from that url changes, but the URL remains the same.
The problem with this is that React does not detect the change, and so does not refresh the image tag automatically, and I have to refresh the page, in order to see the new image.
Here's my code:
class ProfilePage extends Component {
saveImageUrlInDatabase(profileImageURL) {
const imageData = {
profileImageURL: profileImageURL,
};
this.props.uploadProfilePictureURL(imageData);
}
async updateAvatar(event) {
const imageFile = event.target.files[0];
if (!imageFile) {
return;
}
const imageURL = await this.props.uploadProfileImage(imageFile);
this.saveImageUrlInDatabase(imageURL);
this.setState({
profileImageURL: imageURL,
});
}
render() {
const { profile, loading } = this.props.profile;
if (!profile || loading) {
profileContent = <Spinner />;
} else {
// #BUG: Even though profileImageSrc changes
// It doesn't get update automatically
// It turns out the url does not change
// But, the image does change
let profileImageSrc;
// True if user has updated his image
if (this.state.profileImageURL !== "") {
profileImageSrc = this.state.profileImageURL;
} else {
profileImageSrc = !profile.profileImageURL
? require("assets/img/faces/lofi-girl.png")
: profile.profileImageURL;
}
profileContent = (
<Container>
<div className="owner">
<div className="avatar">
<Label for="avatar-upload">
<img
alt="..."
className="img-circle img-no-padding img-responsive"
src={profileImageSrc}
key={Math.floor(Math.random() * 10)}
style={{
cursor: "pointer",
}}
title="Change profile image"
/>
</Label>
<input
id="avatar-upload"
type="file"
accept="image/*"
style={{ display: "none" }}
onChange={this.updateAvatar}
/>
</div>
</div>
</Container>
);
}
return <div className="section profile-content">{profileContent}</div>;
}
}
Any idea how to solve this?
Upvotes: 3
Views: 2272
Reputation: 773
I was facing the same problem: I was updating the image in a url but the url was the same. The image didn't update because the brower saved the image in caché. What I'm doing is to add a random number to the end of the url. If the component is different, it will update alone; otherwise, you can add a button to update the random number. Something like:
const [random, setRandom] = React.useState(1)
render
<button onClick={()=>setRandom(Math.random())}>
update image
<button/>
<img
className = 'img-miniatura'
src = {url+'?n='+random}
alt='miniatura'
/>
Upvotes: 1
Reputation: 4588
Your component has some issue, try this:
import fallbackImage from "./assets/img/faces/lofi-girl.png";
class ProfilePage extends Component {
constructor(props) {
super(props)
this.state = {
profileImageURL: props.profile.profileImageURL,
}
}
saveImageUrlInDatabase(profileImageURL) {
const imageData = {
profileImageURL: profileImageURL,
};
this.props.uploadProfilePictureURL(imageData);
}
async updateAvatar(event) {
const imageFile = event.target.files[0];
if (!imageFile) {
return;
}
const imageURL = await this.props.uploadProfileImage(imageFile);
this.saveImageUrlInDatabase(imageURL);
this.setState({
profileImageURL: imageURL,
});
}
render() {
const { profile, loading } = this.props.profile;
const { profileImageURL } = this.state;
return (
<div className="section profile-content">
{!profile || loading && <Spinner />}
<Container>
<div className="owner">
<div className="avatar">
<Label for="avatar-upload">
<img
alt="..."
className="img-circle img-no-padding img-responsive"
src={
profileImageURL ?
profileImageURL :
fallbackImage
}
key={Math.floor(Math.random() * 10)}
style={{
cursor: "pointer",
}}
title="Change profile image"
/>
</Label>
<input
id="avatar-upload"
type="file"
accept="image/*"
style={{ display: "none" }}
onChange={this.updateAvatar}
/>
</div>
</div>
</Container>
</div>
)
}
}
Upvotes: 0
Reputation: 1
I think you are not declare to React what your state variables are. Normally you need to define the state as described in the docs of React https://reactjs.org/docs/state-and-lifecycle.html#adding-local-state-to-a-class
You would need to do something like this:
constructor(props) {
super(props);
this.state = {profileImageSrc: //the initial url you want}
}
Upvotes: 0