Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Images won't render at the first time #26

Closed
gameboyVito opened this issue Apr 10, 2017 · 25 comments
Closed

Images won't render at the first time #26

gameboyVito opened this issue Apr 10, 2017 · 25 comments

Comments

@gameboyVito
Copy link

In my case, I need to render each image in each row of my listview. The problem is when I install my app and open it at the first time, some of the images just stuck in the loading indicator. However, when I click the image and navigate to another page, that image is shown up in the new page correctly. After I restart my app, the images in the listview are all shown up correctly. Thus, I am guessing that when I open the app at the very first time, the images were downloaded and saved into the cache, but it doesn't lead to rerender the images in the listview. I mean some of them are stuck, the others are loaded successfully. It's not the server's problem, I think it's about how to correctly rerender the cached image in the listview.

And, another problem is that if I updated my profile photo in the server side after I called the onRefresh from the RefreshControl, the uri did change but the cached image wasn't updated. If I press on my photo to open a lightbox which fetches image from the network it shows correctly. I guess this maybe the same issue like above. The image doesn't know when to rerender.......

Do you think it's related to this issue? facebook/react-native#1417

image

image

image

@kfiroo
Copy link
Owner

kfiroo commented Apr 10, 2017

@gameboyVito The RN issue you references indicates there might be an issue with images in an iterator components (such as ListView) and may cause the images not to re-render after the file has been downloaded.
If you have a snippet that reproduces the issue consistently that would be super helpful!

The second issue you mentioned (updating the image on the server) may not be related.
If the image url did not change, i.e. user profile image url is something like https://mysite.com/user-id/profile, the CachedImage component will return the same cached image and will not download it again.
If that is the case, you can manually clear this image from the cache using ImageCacheProvider.deleteCachedImage

@dieunt
Copy link

dieunt commented Apr 10, 2017

Have the same problem, images did not render at the first time install app (using testflight, try to remove it and reinstall). But it work fine when i just kill and open app again.

@kfiroo
Copy link
Owner

kfiroo commented Apr 10, 2017

@dieunt Are the images inside a ListView or any other repeater/iterator component?

@dieunt
Copy link

dieunt commented Apr 10, 2017

@kfiroo yes, it inside a iterator, actually i'm using PullToRefreshListView to render a list of child item.

  • When app start of the first time install app, i will load 10 item from server, it only render image of the first item, other 9 item just show up gray background and the ActivityIndicator.
  • When i'm scroll down to load more 10 items, then the images of that items render normally
  • After restart the app, all images render normally.

@gameboyVito
Copy link
Author

Just like what dieunt said, it'a the same problem I am exactly facing.

@gameboyVito
Copy link
Author

About the second issue, actually my server returns the same URL for the user profile photo. So, what makes me crazy is how to use this great module into a listview. Maybe you can write an example to demonstrate it to us. Thanks

@gameboyVito
Copy link
Author

I really like this repo because you rewrite the out-dated code from jayesbe/react-native-cacheable-image and use react-native-fetch-blob to replace the old one. However, both of these two repo has the same issue on rerendering cached images inside a listview, see this #50. Luckily, I found this repo: wcandillon/react-native-img-cache has no issues on rerendering images inside a listview. So, maybe you can take a look and find out the tricky thing. Look forward to any good news. ^_^

@kfiroo
Copy link
Owner

kfiroo commented Apr 11, 2017

Thanks for the kind words and the info :)

@dieunt The issue you are describing seems to be related to an open react-native issue about images not rendering even when their state / props has been changed (as @gameboyVito pointed out here facebook/react-native#1417)
I will try to get around this issue and update you on the progress.

@gameboyVito Your issue with the profile image is simpler. This module maps urls to local images in a 1-to-1 manner. This means that the same url will have a single file on the disk for it, and if the file exists the module has no way to know the data returned by that url has changed (i.e. the user changed his profile picture).
You would have to remove the file yourself in this process and let the module download the new file to the cache.
Use ImageCacheProvider.deleteCachedImage to remove the local image that belongs to the user profile url, then when you load the image again it will be cached.

@kfiroo
Copy link
Owner

kfiroo commented Apr 12, 2017

@gameboyVito @dieunt Hey, I updated the example project to use a ListView to render the CachedImage components but I can't see the bug :(
Can you try to reproduce it?

@gameboyVito
Copy link
Author

That maybe due to you are using defaultSource in your example. Try to remove it and show your activityIndicator.

@kfiroo
Copy link
Owner

kfiroo commented Apr 14, 2017

I tried with and without defaultSource and it still seems to work well 😕
@gameboyVito @dieunt If you could provide a small snippet that reproduces the issue that would be amazing :)

@shayke
Copy link

shayke commented Apr 16, 2017

I'm having the same issue too :(
Here is a snippet to reproduce it (tested on LG K10)

import React, {Component} from 'react';
import {AppRegistry, Button, Text, TouchableOpacity, View, StyleSheet, ListView, Alert} from 'react-native';

import CachedImage, {ImageCacheProvider} from 'react-native-cached-image';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 20
  },
  buttons: {
    flexDirection: 'row'
  }
});

class CachedImageExample extends Component {

  constructor(props) {
    super(props);
    this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    this.state = {
      dataSource: this.ds.cloneWithRows([]),
    };
    fetch('https://randomuser.me/api/?results=50').then((response) => response.json()).then((responseData) => {
      this.setState({dataSource: this.ds.cloneWithRows(responseData.results)});
    });
  }

  renderRow(x) {
    return (
      <TouchableOpacity>
        <View style={{alignItems: 'center', padding: 10, flexDirection: 'row', borderBottomWidth: 1, borderColor: '#f7f7f7'}}>
          <CachedImage source={{uri: x.picture.large}} style={{borderRadius: 30, width: 60, height: 60}} resizeMode='contain'/>
          <View>
            <View style={{flexDirection: 'row', justifyContent: 'space-between', width: 280}}>
              <Text style={{marginLeft: 15, fontWeight: '600', color: '#222', fontSize: 15}}>{x.name.title}</Text>
            </View>
            <View style={{flexDirection: 'row', alignItems: 'center'}}>
              <Text style={{fontWeight: '400', color: '#666', fontSize: 12, marginLeft: 15}}>{x.location.street}</Text>
            </View>
          </View>
        </View>
      </TouchableOpacity>
    )
  }

  render() {
    return (
      <View style={{flex: 1, marginTop: 20}}>
        <View style={styles.buttons}>
          <Button
            onPress={() => ImageCacheProvider.clearCache()}
            title="Clear Cache"
            color="#6f97e5"
          />
        </View>
        <ListView
          dataSource={this.state.dataSource}
          renderRow={this.renderRow}
        />
      </View>
    );
  }
}

AppRegistry.registerComponent('CachedImageExample', () => CachedImageExample);

@jawinn
Copy link

jawinn commented Apr 17, 2017

Same issue here. I noticed that onLoadEnd is not firing until after the app has been reloaded. Resetting content and settings in the simulator will show the problem again. This is also a component being passed to a ListView.

Using

<CachedImage
onLoadEnd={(e) => { console.log('OnLoadEnd.'); }}
onLoadStart={(e) => { console.log('OnLoadStart.'); }} ...

Used in a component passed to ListView (via renderRow).

First app load:
No messages. Images do not load and show loader indicator forever.

First app refresh:
1 set of messages. First image loads.

Second refresh of app:
2 sets of messages. Both images load.

So it seems to only be loading one additional image per refresh...

Edit: Took this out of a list view and did a simple map(), and still the same issue. On first load, cached image refs appear to be undefined. "undefined is not an object (evlauating this.ref[CACHED_IMAGE_REF].setNativeProps", and adding a then() to the CachedImage.ImageCacheProvider.cacheMultipleImages returns an array with two undefined items within it...this could be the source of the issue?

@ajonno
Copy link

ajonno commented Apr 18, 2017

I'm seeing the same issue also. First image loads, the rest spin. Unmount the view, come back, and all the images load up. There's been a lot of posts on this already but let me know what additional info I can provide.

Really need this fixed soon as we're launching next week. If time is too short to see a fix would also appreciate any workaround others have used to resolve.

image

@ajonno
Copy link

ajonno commented Apr 20, 2017

we've got our <CachedImage> embedded in a _.map(.. ; setting: key=<unique id> prop didn't make any difference unf. any other ideas on a workaround/solution would be great really need it asap. thanks!

@kfiroo
Copy link
Owner

kfiroo commented Apr 20, 2017

@shayke Thanks for the snippet - I'll try it out now!
@jawinn @ajonno Any code samples would be great!

@kfiroo
Copy link
Owner

kfiroo commented Apr 20, 2017

@shayke @jawinn @ajonno @gameboyVito @dieunt
I found an issue with android and fixed it, I got the example working on Android and iOS.
If you could pull master and confirm I would release a new version with the fixes :)

@ajonno
Copy link

ajonno commented Apr 21, 2017

thanks for getting back on this sounds awesome. sorry can u clarify how you want us to test it? eg. i just downloaded the zip of this repo and ran the example app, and the issue still exists. or should i set a specific dependency in package.json etc. "react-native-cached-image": "*" ?

@kfiroo
Copy link
Owner

kfiroo commented Apr 21, 2017

@ajonno Hey, latest version of the example app should be working, not sure why the difference between our setups :(

This is what I do to set up:

git clone https://github.com/kfiroo/react-native-cached-image.git
cd react-native-cached-image
cd CachedImageExample
yarn
#this will start a process that will copy the lib files as they change - you can stop it after the first copy
yarn run dev
react-native run-ios
#or
react-native run-android

In the simulator, I first clear cache with the button at the top, then reload the app to see the images load.

@ajonno
Copy link

ajonno commented Apr 21, 2017

thats exactly what i did too (i think!). let me try again now and ill let you know.

@ajonno
Copy link

ajonno commented Apr 21, 2017

all done, looked great. i added in some extra images to the array for good measure and they all loaded up. thanks for the quick response!

@kfiroo kfiroo closed this as completed Apr 21, 2017
@aravindhkumar23
Copy link

aravindhkumar23 commented Aug 14, 2017

@kfiroo @ajonno iam facing the same issue in flatlist
1st spinner is loaded with default source as background
and after download the image a blank screen is shown but if i use the same uri in a modal iam getting the image from cache my frame is not updated with original image.

my code looks like this

<TouchableHighlight key={index+"image"} style={{width:Dimensions.get('window').width-80,height:270,backgroundColor:'white',alignSelf:'center',alignItems:'center',justifyContent:'center'}} onPress={()=>{that.setModalVisible(true,element.image)}} underlayColor='transparent' >
    <CachedImage
        source={{uri: element.image}}
        defaultSource={require('../img/default.png')}
        fallbackSource={require('../img/default.png')}
        style={{width:Dimensions.get('window').width-80,height:250,resizeMode:'contain'}}
    />
</TouchableHighlight>

@hugomosh
Copy link

Is this happening on android only?
This could be the problem: facebook/react-native#13600
Any solution?

@JustinKasad
Copy link

My issue was caused by fallbackSource

Removing that prop fixed the issue

@jeremyfrancis
Copy link

It looks like for me the issue was that I had a Animated.Image and changing it to just a react native Image seemed to solve the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants