kfiroo / react-native-cached-image Goto Github PK
View Code? Open in Web Editor NEWCachedImage component for react-native
License: MIT License
CachedImage component for react-native
License: MIT License
I'm experiencing something weird when downloading images with the ImageCacheProvider. I have ~15 images being downloaded the first time I open my app. I can confirm they're being successfully saved but every time I have to load them I can see the following behaviour:
1 - I open a new window that has a CachedImage component on it.
2 - The CachedImage component doesn't show up at all (just like it has height: 0 and width: 0
3 - After ~200ms the CachedImage component shows up as a blank square (height and width are now correctly set
3 - After ~200ms the ActivityIndicator shows up
4 - After ~200ms the image finally shows up.
Is that normal/expected? How can I prevent that transition between steps 2-3 (where I can see the image container growing) ? Thanks!
After upgrading to latest React Native (0.48.0) I keep getting this warning:
NetInfo's "change" event is deprecated. Listen to the "connectionChange" event instead.
I guess this is due to:
react-native-cached-image/CachedImage.js
Line 90 in 6aac317
The native <Image />
component has no problem serving over HTTPS, however this component is for some reason not loading anything over HTTPS. Changing the link to an HTTP link works fine. However, my CDN requires a HTTPS connection.
For example, the following will not load
<CachedImage source={{uri: 'https://firebasestorage.googleapis.com/v0/b/qualify-college-dating.appspot.com/o/user_photos%2Fc9bd1771-e08c-4fc4-986d-7658776e6491?alt=media&token=9dae0c20-ef0a-40e9-ad87-25a8b8460f5c'}} style={{width: 300, height: 300}} />
However, the link in the browser loads the image fine, but something like
<CachedImage source={{uri: 'http://placehold.it/256'}} style={{width: 300, height: 300}} />
Loads just fine, also the native component loads just fine
<Image source={{uri: 'https://firebasestorage.googleapis.com/v0/b/qualify-college-dating.appspot.com/o/user_photos%2Fc9bd1771-e08c-4fc4-986d-7658776e6491?alt=media&token=9dae0c20-ef0a-40e9-ad87-25a8b8460f5c'}} style={{width: 300, height: 300}} />
I'm completely uninstalled and re-installed the application and even did some debugging by creating a fork, which shows that the image is being downloaded and saved to disk. The image on the disk is being found during the getCachedImagePath
call as well. The path being returned in the CachedImage.js
render() call is as follows:
Source: { "uri": "file:///Users/christiantucker/Library/Developer/CoreSimulator/Devices/4D19844A-CAEA-4CCA-A3C6-328C58CC6AFA/data/Containers/Data/Application/6C8A618F-0ED7-4F69-8CBE-A80F5DFA2CB1/Documents/firebasestorage.googleapis.com/4c79bcb33ecdfe4512febf4c97c40cb86082398d.com/o/user_photos%2Fc9bd1771-e08c-4fc4-986d-7658776e6491" }
This problem persists with any HTTPS link, even the ones in your example. All HTTP links are fine.
This may actually be a problem with react-native-fs as I've created my own caching implementation in the last few hours and I have the same problem with HTTPS.
Cache means NOT PERSISTENT.
Now, I must record the time when an image been cached, and invoke the delete method over a period of time manually. So, I think it could be better to provide an option to set expiration policy.
Hi there!
Just want to kindly ask if you could remove the statement, that react-native-fs is not maintained any more as it is active back again :) I am the new maintainer since some days.
thx and regards!
TypeError: RNFatchBlob.config(...).fetch(...).then(...).catch(...).finally is not a function
Where allImages
is an array containing two image URLs, this catches an error:
CachedImage.ImageCacheProvider.cacheMultipleImages(allImages)
.then(resp => {
console.log('cacheMultipleImages Done');
})
.catch(err => {
console.log('cacheMultipleImages caught an error: ', err);
});
Also, looks like the version number on the repo needs to be updated to 1.3.2 to match the latest release number?
Hey - great work on this component!
I found that currently, attempting to nest a <CachedImage/>
as a child inside a <TouchableOpacity/>
throws:
Invariant Violation: Touchable child must either be native or forward setNativeProps to a native component.
This is blocking us and may block others so I have submitted a PR to resolve this issue: #3
If the download of the image returns a status code that represents an error the body content is still stored as the image file, even though it's probably an error message.
The status code of the result coming back from RNFS.downloadFile should be taken into account. I suggest any 2xx status be considered a success and any other status code a failure. Note: 3xx redirects look to be taken care of by RNFS.downloadFile.
Hi kfiroo,
If I add resizeMode to CachedImage style, it will cause warning
<CachedImage style={{resizeMode:Image.resizeMode.stretch}} source={{uri:item.img}} />
Warning: Failed prop type: Invalid props.style key `resizeMode` supplied to `ActivityIndicator`.
Bad object: {
"width": 360,
"height": 592,
"resizeMode": "stretch",
"opacity": 0,
"backgroundColor": "transparent",
"alignItems": "center",
"justifyContent": "center"
}
...
in ActivityIndicator (created by CachedImage)
in CachedImage (created by TopBannerItem)
Warning: Failed prop type: Invalid props.style key `resizeMode` supplied to `View`.
Bad object: {
"alignItems": "center",
"justifyContent": "center",
"width": 360,
"height": 592,
"resizeMode": "stretch",
"opacity": 0,
"backgroundColor": "transparent"
}
...
in View (created by ActivityIndicator)
in ActivityIndicator (created by CachedImage)
in CachedImage (created by TopBannerItem)
I have read your source code and found that there is no way to pass a customised loading spinner to replace the default ActivityIndicator. The default one is ugly and I would like to replace it with my own component. Maybe you can just rewrite renderLoader()
to support this feature. Or I can just send you a PR if you are acceptable.
In my program, each user can have a avatar, for example: http://www.mywebserver/avatar/username.jpg
When a user request http://www.mywebserver/avatar/username.jpg, my server will check the request headers last-modified(and I need add cached image's last-modifiled at request header) ,
if the cached image's last-modified time is equal to the server save tiem, the server will return 304 and do not return the image data.
otherwise, the server will return image data and rn app need remove last cached image and cache new image for same url(http://www.mywebserver/avatar/username.jpg).
Is there any way that I can to do?
How to set the cache size? Tons of images will be cached in the local storage, methods to check the current cache size and delete all cached files, or a prop to set the limit of cache size would be very helpful.
React has deprecated PropTypes from React
and is now giving a warning in RN 0.45.0 and up.
Should be an straight replacement in the code I can do a PR if you are interested.
Even though your code in github did a fix for that (PR), the code from npm (version 1.4.0) is still 'wrong' as it is using the wrong eventName (change
instead of connectionChange
NetInfo.isConnected.addEventListener('change', ...)
The listener is also not correct:
handleConnectivityChange(isConnected) {
this.safeSetState({
networkAvailable: isConnected
});
}
The parameter when the listener is called is not a boolean (as you expect in your code) but an enum
using:
npm install react-native-cached-image --save
and later
react-native link react-native-fetch-blob
.
react-native -v
react-native-cli: 2.0.1
react-native: 0.33.0
"react": "~15.3.2",
"react-native": "0.33.0",
i'm follow this for fix it, but notting works
I've been using CachedImage for sometime but I never managed to see the activityIndicator on Android, while on iOS it works as expected.
I have the ACCESS_NETWORK_STATE on Android Manifest, the caching works, but when loading the image I can only see a blank space.
Am I missing something?
Tested on 1.3.5 and 1.4.0-rc
React Native: 0.47
"Warning: Failed prop type: Invalid props.style key tintColor
supplied to ActivityIndicator
."
Suggested solutions:
render() {
return (
<View>
<TouchableWithoutFeedback onPress={() => {
this.setState({showModal: true})
}}>
<CachedImage
source={{uri: 'http://p10.qhimg.com/t019e9cf51692f735be.jpg'}}
resizeMode="contain"
style={{width: 100, height: 100}}
/>
</TouchableWithoutFeedback>
<Modal
visible={this.state.showModal}
animationType='fade'
onRequestClose={() => {
this.setState({showModal: false})
}}>
<TouchableWithoutFeedback onPress={() => {
this.setState({showModal: false})
}}>
<CachedImage
source={{uri: 'http://p10.qhimg.com/t019e9cf51692f735be.jpg'}}
resizeMode="contain"
style={{flex: 1}}
/>
</TouchableWithoutFeedback>
</Modal>
</View>
)
}
If the first image is being downloaded and then I turn on the Modal, Modal will show an incomplete picture.This means that the download is closed and a wrong image is retained.
I am using react-native-cached-image, there are some mistake when use CachedImage.
the code:
<CachedImage
source={{
uri: item.img
}}
defaultSource={require('../images/fail1.png')}
style={{width:(widthMsg2)*0.5, height:imgH}}
fallbackSource={require('../images/default.jpg')}
/>
the error is follow:
[RCTImageShadowView.m:20] Using with children is deprecated and will be an error in the near future. Please reconsider the layout or use instead.
anyone help me ?
I don't want to show a ActivityIndicator in CachedImage, how to hide it?
Is there a way to know when a cached image is available ? By that i mean specifically when the activity indicator has completed ?
I'd like to have a completion callback, that I could then use to re-enable some components etc
Many thanks!
As the library uses react-native-fetch-blob for the download and by default, react-native-fetch-blob does NOT allow connection to unknown certification provider since it's dangerous.
It is not a suprise that cached image also not support that. But sometimes it is needed to accept also self signed stuff. To connect a server with self-signed certification, you need to add trusty to config for react-native-fetch-blob explicitly.
RNFetchBlob.config({
trusty : true
})
The cached image actually just use the path property.
It is easy to add the trusty flag, but I would like to ask the community what they would like to have.
I would like to add a PR for that but first would like to ask you :D
Hmm... I have an idea!
What if we render image only when renderImage
property is available?
We do not need CachedImage component either.
<CachedImageProvider sources={[...images]} renderImage={props => (
<ResponsiveImage {...props} />
)} />
See pull request #12
hi, I'm not totally clear on how the .seedCache option works re params so was hoping you could assist.
For ex. I've got this:
ImageCacheProvider
.seedCache(dirs.DocumentDir + '/IMG_7091.PNG', IMAGE_PREFETCH_URL)
.then((response) => {
console.log('seeding cache SUCCESS', response);
})
.catch(error => console.log('error seeding cache', error));
Param 1 is the input file / the path to the on device image.
questions related to this:
what is the destination path ? it looked to me like the copied file is landing (on iOS) here:
/../../Library/Caches/imagesCacheDir/firebasestoragegoogleapiscom/<the file>
can I set the output/destination folder in the Caches folder or is it currently hardcoded to imagesCacheDir/firebasestoragegoogleapiscom ?
trying to understand why the file is being renamed when it is copied into the destination folder ? for example my source file name was IMG_7091.PNG
whereas the destination file was f4ed3ea4e0872d196b655787291a8b7d972daaa1.png
Param 2 - I couldnt figure out what this would do / how it fit in ?
Param 3 - I believe these are covered already in the docs
Package must use latest version of react-native-fs to work with RN 0.40
Hello,
I'm having some problems the first time i declare a CachedImage.
It looks that it's trying to find the image and the error is not being handled.
Do you experience the same problem?
YellowBox.js:71 Possible Unhandled Promise Rejection (id: 0): The file “50c5db50fca5ad9306dce6d1e947ba1781e0ab41.jpg” couldn’t be opened because there is no such file. Error: The file “50c5db50fca5ad9306dce6d1e947ba1781e0ab41.jpg” couldn’t be opened because there is no such file.
Nice module,
Keep the good work
If a URI is no longer available but the image is already in the cache, the cached version is displayed. However, if the image is not available in the cache, the activity indicator shows forever. Is there a way to specify a placeholder or default image to use when the URI is invalid or no longer available? defaultSource
doesn't work for me, with or without borderRadius
being set, but I suspect that even if it did, I'd still see the spinner.
hi there, thanks for this library !
can you provide quick example of how useQueryParamsInCacheKey
can be used ?
also im not sure if this is/should be, a feature of this library but is it possible to apply (lets say) a "tag" to an image so that later, we can retrieve it via a query=tag
?
Would be nice if CachedImage had a "forceFetch" parametter (default to "false") allowing to force the image to be redownloaded even if it is already in cache (and by the time it is downloaded, the old image in cache could be used as a "defaultSource" unless it do not exist in cache or a "defaultSource" parametter is already provided in the CachedImage tag)
hi, i was testing out the seedCache option today and was getting a promise error telling me no such file exists. I may well have the path syntax wrong here so wanted to check.
The dirs.Documents
folder is the on device "Documents" folder (which I'm getting via react-native-fetch-blob
and I know via other use that it works/resolves correctly)
The IMAGE_URL
is a Firebase Storage endpoint for an image.
Here is the call:
ImageCacheProvider.seedCache(`${dirs.Documents}/2017-04-18_09-24-25.png`, IMAGE_URL);
That would work the same but use an Animated.Image
so images can be animated (e.g. fading for progressive images). That's something I would be keen to look at if I get the go for a PR from one of the maintainer.
I tried to use ImageCacheProvider.getCachedImagePath()
function to access downloaded local files with URL links, but I don't know how to use the returned Promise<imagePath: string>
. The result is shown as follows:
I outputted the Promise<imagePath: string>
.
The first line shows the value of key _65
is null and it‘s indeed null when I try to get this value in my app. But why can I see a local path after expanding the node and how can I use it?
Hello, I've got a question.
I need to prefetch and cache hundreds of photos from an API to implement an offline-mode for an app. The total file size may exceed 1GB.
When I tried to download the images using the cacheMultipleImages
function it crashed the app due to out of memory errors.
Is it possible to use this component for such a usecase?
Do you have any ideas on why it runs out of memory? Can anything be done about that?
Thank you!
Partial stacktrace before the crash:
05-05 17:06:57.487 22522-22619/com.app E/unknown:React: Exception in native call
java.lang.RuntimeException: Could not invoke RNFetchBlob.fetchBlob
at com.facebook.react.bridge.BaseJavaModule$JavaMethod.invoke(BaseJavaModule.java:382)
at com.facebook.react.cxxbridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:138)
at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:31)
at android.os.Looper.loop(Looper.java:148)
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:208)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.facebook.react.bridge.BaseJavaModule$JavaMethod.invoke(BaseJavaModule.java:368)
at com.facebook.react.cxxbridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:138)
at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:31)
at android.os.Looper.loop(Looper.java:148)
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:208)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Try again
at java.lang.Thread.nativeCreate(Native Method)
at java.lang.Thread.start(Thread.java:1063)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:921)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1339)
at okhttp3.Dispatcher.enqueue(Dispatcher.java:129)
at okhttp3.RealCall.enqueue(RealCall.java:78)
at com.RNFetchBlob.RNFetchBlobReq.run(RNFetchBlobReq.java:372)
at com.RNFetchBlob.RNFetchBlob.fetchBlob(RNFetchBlob.java:317)
at java.lang.reflect.Method.invoke(Native Method)
at com.facebook.react.bridge.BaseJavaModule$JavaMethod.invoke(BaseJavaModule.java:368)
at com.facebook.react.cxxbridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:138)
at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:31)
at android.os.Looper.loop(Looper.java:148)
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:208)
at java.lang.Thread.run(Thread.java:818)
Author of the library points to react-native-fetch-blob as an alternative
Hi, local images successfull showing but server images not show android.
Im add
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Problem still is continue...
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
The cacheGroup key is not included in the options selected from the component props.
https://jmperezperez.com/medium-image-progressive-loading-placeholder/
if possible, can you help to support get cache size?
Thanks for sharing fantastic library. I got stuck with managing profile picture. The cached image looks like working well, but if the user change his profile picture the image won't be refreshed.
Let's suppose there is a profile screen using CachedImage
.
<CachedImage
source={{uri: 'http://myapp.com/user001'}}
/>
If a user change profile picture, server will get his picture and overwrite it. (Because it saved with user name).
At this point, local cached profile image
and server's profile image
is different. right?
And then how can I notice to device
Please, the server's image changed. Cache fresh one again.
?
I tried when I success upload new image, remove cached image using cachedImageProvider
, If I do that the image become empty. And without this, the image won't changed to latest one. How can I use it properly? It is because of redux problem?
Now I am using like this...
<CachedImage
source={{uri: this.props.user.profileImageRef}}
/>
The files paths are coming without prefix file://
on Android, because that, the file address becomes incorrect, so I need to append file://
to file path.
On iOS it's ok.
I'm using getCachedImagePath
method.
Thank you for the lib, it's very awesome!
If you need some help, please let me know.
Hi!
In our app, we have the following scenario:
react-native-fetch-blob
. Getting an url back as a reference.So - As an optimization for the sending device, we would like to be able to supply the local image from the first step, as a cache for the url returned.
var supplyResponse;
try{
supplyResponse = ImageCacheProvider.seedCache('https://remote-image-service.com/img-1.png', '/some-local-path/img-1.png');
} catch(err) {
//Could not read local file
}
ImageCacheProvider.seedCache
would then copy the file /some-local-path/img-1.png
to the appropriate path.
Hi,
I'm using this component but on iOS I've a blink effect on my cachedImage component ! On a listview, when i tap on an item and a new page appear, my image into my list blink ! And the same thing appear when i go back to my list !
But on Android everything it great! I've test on Debug and Release mode!
Whenever I use resizeMode in style I get a React warning:
Warning: Failed prop type: Invalid props.style key 'resizeMode' supplied to 'ActivityIndicator'.
It seems as if the style given to CachedImage is used on both the ActivityIndicator
and the Image
elements. Is there a way to get the separate styles to them?
<CachedImage
useQueryParamsInCacheKey
style={{ resizeMode: 'contain' }}
source={uri}
/>
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.