facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
118.35k stars 24.25k forks source link

Image never reloads with same uri #12606

Open RyanMitchellWilson opened 7 years ago

RyanMitchellWilson commented 7 years ago

I am using an Image component to display a profile picture but no matter what I do to the image component it will not reload the image. I have to use the same url for the profile pictures so I tried to give the Image a unique key prop to try and get it to reload the image but it still just uses the image from cache. I have changed the image on the server countless times but the Image component only shows the original image it got for the url.

It would be great if there was a prop to pass into Image that forces it to refresh the image every time it is rendered.

In a perfect world it would display the image from cache while fetching the new image, compare the two then decide if the image has changed.

ramilushev commented 7 years ago

@RyanMitchellWilson What I do as a workaround is add a meaningless query parameter to the url. Now whenever I want the image to reload, I just change that param and that invalidates the cache.

RyanMitchellWilson commented 7 years ago

So it turns out I was actually hitting the wrong dev environment for the picture so it just looked as though it wasn't changing when it actually was.

RyanMitchellWilson commented 7 years ago

Well it seems I was actually right the first time so I'm going to reopen this issue. I even gave the image a key of Math.random() and it still keeps loading from cache when the image on the server has changed multiple times

RyanMitchellWilson commented 7 years ago

Using @ramilushev suggestion worked but it feels hacky and probably shouldn't be needed.

LEEY19 commented 7 years ago

@RyanMitchellWilson have you found a better solution to this ever since then? I do feel that this is an issue that the developers in FB have to look into. its been re-raised and no good solution has been given till now

huangmr commented 7 years ago

Same issue here (only this time with FB account images, LOL). On iOS the image seems to refresh okey-ish after the image view is unmounted, and it also has a cache props for that. On android the image is cached for ever unless do something like @ramilushev suggested, although it is only a workaround and not without side effects (e.g. no cache to use after path change, producing too many junk copies in the cache for the same image). The issue probably boils down to the Fresco library (the Image component uses internally), which currently doesn't seem to have a good knowledge about when to invalidate its cache, and there is no current way of forcing it to invalidate either (or if there is one please let us know).

wuyunqiang commented 7 years ago

ios I can set <Image key ={this.count++} style={{width:SCALE(200),height:SCALE(70)}} source={{uri:ver,cache: 'reload'}}/> and is ok. but android stil bad. please let me know if it be solve.

stale[bot] commented 6 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. If you think this issue should definitely remain open, please let us know why. Thank you for your contributions.

RyanMitchellWilson commented 6 years ago

This is still a problem

dbyilmaz commented 6 years ago

@RyanMitchellWilson
Did you solve the problem?

RyanMitchellWilson commented 6 years ago

@dbyilmaz Not exactly I'm still using the work around stated above adding a Math.random() to the query string in a way that doesn't affect the url. This causes the url to be different every time so it will actually fetch the image instead of just grabbing it from the cache.

dbyilmaz commented 6 years ago

@RyanMitchellWilson I am using your workaround. I think it is not good. I guess facebook don't think to solve this problem.

hyochan commented 6 years ago

@RyanMitchellWilson @dbyilmaz you can fix this problem by adding new Date() value in key. like

<Image
  key={new Date()}
  style={styles.drawerAccountImg}
  source={uri: this.state.photoURL}
/>

However, I've not tested in android yet.

malinamircu commented 6 years ago

Hi

This worked for me on Android emulator:

<Image key={(new Date()).getTime()} source={{ uri: global.SERVER_ROOT + item['LOGO_IMG']+'?time'+(new Date()).getTime(), headers: {Pragma: 'no-cache' } }} style={{ width: width / 5, height: 100 }} />

Hope it hepls Malina

crazyfree commented 6 years ago

add a query string after url, works for both platform <Image style={styles.drawerAccountImg} source={uri: this.state.photoURL + '?' + new Date()} />

aswin2772 commented 6 years ago

Thankz bro...

dbarros commented 6 years ago

Adding a query param to the source works. But it's all too hacky.

Padillahirpan commented 6 years ago

i'm still cant believe its really works

indrajeet1629 commented 6 years ago

add a 'time=' param along with image URL, works as well.

<Image source={ { uri : this.props.userData.profileImgURL + '?time=' new Date() }} />

Dror-Bar commented 6 years ago

Still an issue - cache: 'reload' doesn't work on Android. Only hacky solutions work but they put a lot of junk images in the cache which is bad...

tokinonagare commented 6 years ago

Still an issue, wish to resolve : )

Faolain commented 6 years ago

+1

I-O-O-I commented 6 years ago

<Image source={{uri: , CACHE: 'reload'}} />

CACHE prop worked for me.

Dror-Bar commented 6 years ago

@I-O-O-I As mentioned in the thread, that is for IOS only, it does not work for Android.

ahpollen commented 6 years ago

+1

singhal-akash67 commented 5 years ago

<Image style={{flex:3,width:'100%'}} source={{uri: image.thumbnailUrl+'?'+new Date().getDate()}} key={image${i}}/> This worked for me, currently react native does not have support for android, so we need some kind of hack

harikanammi commented 5 years ago

hi, i am using this property for android:-

<Image
source={uri: this.state.uri + '?' + new Date()}
/>

For iOS:- <Image source={{uri: this.state.uri, CACHE: 'reload'}} />

But any changes doing in that particular screen then image is disappearing like below mentioned gif file :- ezgif com-video-to-gif Please give any suggestion for this issue.

habibiazmi123 commented 5 years ago

same issue @harikanammi

zoix commented 5 years ago

I haven't tried this, but in Vue the same happened to me. It didn't work with Date() but it worked with Math.random(). It would be something like this:

<Image source= { uri: this.state.uri + '?rnd=' + Math.random() } />

harikanammi commented 5 years ago

hi @agamadev, thank you for your reply. <Image source= { uri: this.state.uri + '?rnd=' + Math.random() } /> this is not working for me. Image disappearing issue is not fixed.

Salakar commented 5 years ago

Hey all. Thanks for reporting this and posting workarounds. It'd be great if someone could send a PR to support some (if not all) the same options as iOS currently does.

If it helps in creating a PR; the native Image view code can be found in the following places;

Internally this uses Fresco's ImagePipeline, which has various caching controls as seen here in the source.

pbitkowski commented 5 years ago

So we want to implement cache property for source on Android with the same implementation as iOS? For reference: https://facebook.github.io/react-native/docs/images#cache-control-ios-only

ashishgunjal5896 commented 5 years ago

add a query string after url, works for both platform <Image style={styles.drawerAccountImg} source={uri: this.state.photoURL + '?' + new Date()} />

Thanks it Working.. :)

ashishgunjal5896 commented 5 years ago

Can someone tells React Native 0.59 is stable to upgrade. Currently using 0.57

jimmydjabali commented 5 years ago

Yes, this is still a big issue in RN for Android I think..

It means that we just can't ever update the cache of an image when it's downloaded for the first time, unless flushing the whole app's cache.

dann1609 commented 5 years ago

Workaround work too with local images like /storage/.../asdasd.jpg

cpojer commented 5 years ago

Is there anybody who could send a PR like @Salakar was proposing?

Usamaliaquat123 commented 5 years ago

what a problem bro 💐

bimalgrg519 commented 5 years ago

I am planing to ask my backend developer to send date of image created along with image uri.

panda0603 commented 5 years ago

is this still an ongoing issue? been couple of years now

papidb commented 4 years ago

Yeah I think so

jacquesdev commented 4 years ago

I had to do a forcedUpdate and add key

componentDidMount() {
    setTimeout(() => {
      this.forceUpdate()
    }, 2000)
  }

Simply adding key={new Date()} seemed to do the trick for me, even though I see it doesn't seem to key prop available.

Nothing else worked for me, but this fixed it in iOS and Android

lakhvirk commented 4 years ago

I fixed this issue by adding random string. This is similar to adding date but it wasn't working for me because i may need to encode url for spacing.

<Image
    style={styles.image}
    source={uri: `${this.state.photoURL}&random=${Math.random().toString(36).substring(7)}`}
/>

OR If you don't have existing parameters in that image url.

<Image
    style={styles.image}
    source={uri: `${this.state.photoURL}?random=${Math.random().toString(36).substring(7)}`}
/>
mechazod commented 4 years ago

@malinamircu It works for me when appending date time in photo URL, but it will flicker the image.

formaldehydeson commented 4 years ago

would be nice if there was a way to flush the image cache for scenarios like this @mechazod to fix the flicker thing I'm setting

this.state = {now: Date.now()}

in my constructor and using that as the image URL parameter so that it doesn't re-download the image every time the component re-renders

mechazod commented 4 years ago

@formaldehydeson Yes, that will be a great idea to avoid the flicker effect.

xstable commented 4 years ago

You also can set new Date().getDay() instead of Date.now(), this way it's only refreshed once a day (e.g. if Image is not such important to refresh [or use hours, minutes....). This way, the refresh isn't that often (which will result in better App-Performance and lower Network-Traffic)

At least, all those Solutions are really ugly and bad for the App-Performance. In my case, it seems to happen only at some Android-Devices (not at IOS at all). I'm not yet figured out, if it's the Android-Version or special Devices (maybe Manufacturer Changes at the OS).

But I would heavily appreciate if this bug will be analysed and solved soon.

EricWiener commented 4 years ago

I'm having this issue with a local image. The image is being changed but kept at the same absolute path. The Image component is not re-rendering. I tried CACHE: 'reload', but it doesn't help.

formaldehydeson commented 4 years ago

Since my issue here was with user uploaded profile picture images, I ended up adding a timestamp in their profile with the last time they updated their profile picture and I'm appending that to the image url instead of using a date value set in the component constructor. Still pretty annoying that I need to result to that but it gives the best user experience with the least amount of unnecessary re-loads.

duclahoang commented 4 years ago

add a 'time=' param along with image URL, works as well.

<Image source={ { uri : this.props.userData.profileImgURL + '?time=' new Date() }} />

Thanks a lot! 👍