GithubHelp home page GithubHelp logo

wcandillon / react-native-expo-image-cache Goto Github PK

View Code? Open in Web Editor NEW
667.0 17.0 125.0 514 KB

React Native Image Cache and Progressive Loading based on Expo

License: MIT License

TypeScript 100.00%

react-native-expo-image-cache's Introduction

React Native Image Cache and Progressive Loading

CircleCI npm version

React Native image cache and progressive loading for iOS and Android. Based on Expo Kit.

This is a component used in the React Native Elements and the React Native Fiber starter kits.

Checkout this medium story about react-native-expo-image-cache.

Installation

This package has a peer dependency with React, React Native, and Expo.

yarn add react-native-expo-image-cache

Usage

Props

Props Default Options
tint dark light, dark, default
transitionDuration 300 custom in ms

import {Image} from "react-native-expo-image-cache";

// preview can be a local image or a data uri
const preview = { uri: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" };
const uri = "https://firebasestorage.googleapis.com/v0/b/react-native-e.appspot.com/o/b47b03a1e22e3f1fd884b5252de1e64a06a14126.png?alt=media&token=d636c423-3d94-440f-90c1-57c4de921641";
<Image style={{ height: 100, width: 100 }} {...{preview, uri}} />

CacheManager

Get the local image from a remote URI

import {CacheManager} from "react-native-expo-image-cache";

const {uri} = this.props;
const path = await CacheManager.get(uri).getPath();
// if path is undefined, the image download has failed 

You can also clear the local cache:

import {CacheManager} from "react-native-expo-image-cache";

await CacheManager.clearCache();

react-native-expo-image-cache's People

Contributors

animawolf avatar brendan-jefferis avatar brunohkbx avatar dependabot[bot] avatar fenghengzhi avatar koenpunt avatar louisjs avatar mindfreeze avatar vkedwardli avatar wcandillon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-expo-image-cache's Issues

`preview` not resize with require('image/path')

Thanks for this awesome library!

When I try preview with the local image face the following issue, image fetch with uri seems ok:
screen shot 2018-04-08 at 8 42 18 pm

Version: 2.0.2

        if (images && images[0]) {
            return <Image resizeMode={'stretch'} style={{ height: 100, width: 100 }} {...{ uri: images[0].imgUrl }} />;
        } else {
            return (
                <Image
                    resizeMode={'stretch'}
                    style={{ height: 100, width: 100 }}
                    {...{ preview: require('../../assets/images/mini.jpg') }}
                />
            );
        }

Warning: Failed prop type: Invalid prop `source` supplied to `Image`.

Hi, this repo is really a great improvement for Expo Images.
But this warning raised recently.

<CacheImage
        preview={getAvatarPlaceholder}
        uri={data.creator.photoURL}
        style={styles.userPic}/>

export const getAvatarPlaceholder = () => {
    return require('../assets/images/avatar-placeholder.png');
};


Warning: Failed prop type: Invalid prop `source` supplied to `Image`.
    in Image (at Image.js:92)
    in Image (at DiscoverScreen.js:347)

In output, it states that the error happens in Image.js:92 which is about preview.

Dependencies

Hey,

Can you explain the need for the dependencies? Especially

"babel-cli": "^6.26.0",
"babel-preset-react-native": "^4.0.0",
"crypto-js": "^3.1.9-1",

I think the rest could be omitted as well?

Usable with ImageBackground?

Using <Image> with children is deprecated and will be an error in the near future. Is it possible to easily integrate this library with the new <ImageBackground>?

Cache entry downloaded multiple times

Hi, I notice if a particular image that is repeated multiple times, there will be multiple downloads of the image. It looks like while a single cache entry is created, calling getPath() on it multiple times will result in multiple downloads (until one of them has completed).

Maybe there could be a single promise for the cache entry which handles the downloading?

Cleanup subcription

At the moment when the component unmounts we don't clean up the observer subscription.

Expo V33.0.0 FileSystem, BlurView

Hi, I have a problem with react-native-expo-image-cache since Expo upgraded to 33.0. Now FileSystem and BlurView are imported separately.
How can I continue to use react-native-expo-image-cache? It's a good module for me.

possible to support tintColor?

Similar to #35 (resizeMode), it would be great if we could support tintColor.

tintColor is an RNImage-specific style prop, and not a valid style prop for normal Views. So we'd need to stuff it into computedStyle for RNImage, and be sure not pass it to the outermost view's style.

I can make a PR if it would be helpful.

Unhandled Rejection (Error): The method or property expo-file-system.getInfoAsync is not available on web, are you sure you've linked all the native dependencies properly?

Would it be possible to add fallback to react-native's native Image component if the platform is web?

Right now I'm doing this as a workaround:

...
import * as Cached from 'react-native-expo-image-cache';
import { Image, Platform } from 'react-native'

const Img = Platform.OS === 'web' ? Image : Cached.Image;

However, this isn't exactly ideal. I'm using it with expo web, and getting this error:

Unhandled Rejection (Error): The method or property expo-file-system.getInfoAsync is not available on web, are you sure you've linked all the native dependencies properly?

Thanks so much!

"The Expo SDK requires Expo to run" red screen

Does this module only work with Expo apps, or apps that were once on Expo, but subsequently ejected?

I ask because I'm trying to use the module against an app that has never been on Expo, and it's red screening with the following error:

The Expo SDK requires Expo to run. It appears the native Expo modules are unavailable and this code is not running on Expo

I've added Expo as dependency, yarn add expo. Is there something else that I need to do?

SyntaxError in /node_modules/react-native/Libraries/StyleSheet/StyleSheetTypes.js

I'm getting this error:

error: bundling failed: SyntaxError in /Users/tommy/Git/noisolation/FamilyFrame/node_modules/react-native/Libraries/StyleSheet/StyleSheetTypes.js: /$project_path/node_modules/react-native/Libraries/StyleSheet/StyleSheetTypes.js: Unexpected token, expected { (18:7)
  16 | import AnimatedNode from 'AnimatedNode';
  17 |
> 18 | export opaque type StyleSheetStyle: number = number;
     |        ^
  19 |
  20 | export type ColorValue = null | string;
  21 | export type DimensionValue = null | number | string | AnimatedNode;

My code:

import { Image as CachedImage } from 'react-native-expo-image-cache';

class Class extends Component {
    render() {
        const preview = require('./img/image.png');
        const uri = this.props.imageURI;
        
        return <CachedImage style={{ height: 100, width: 100 }} {...{ preview, uri }} />;
    }
}

Anyone else experienced this?

Unable to resolve "@unimodules/core" from "node_modules/expo-blur/build/BlurView.ios.js"

I'm getting this error:
Unable to resolve "@unimodules/core" from "node_modules/expo-blur/build/BlurView.ios.js"

Fully managed Expo project, not ejected, running Expo SDK 32.
I've created a separate branch and updated expo sdk to 33 and it works fine.
The thing is, most of our live apps are still running expo sdk 32 and it will be a while until we get all of them updated, and I really wanted to start using this library.

Anybody has any idea on how to solve this?

I've already tried updating both node and npm, deleting node_modules and running npm install again, removing the expo app from the simulator and running expo again to get the updated app, none of these solved the problem.

Before that error, I was getting this error :
Unable to resolve "expo-blur" from "node_modules/react-native-expo-image-cache/dist/module/Image.js"

Then, I manually installed expo-blur with npm, and started getting the error mentioned in the title. Maybe those are related? I don't know.

Any help is appreciated.

CacheManager - Cache validation

First of all, great idea.
I had issues relying on Image.prefetch so your approach to the caching situation makes life a bit easier, although fetching multiple data files/ images at once (via Promise.all) React Native might make the app unresponsive. Using something like es6-promise-pool gets the job done regardless of how many Promises you generate.
Image.prefetch doesn't have this issue, as it most probably uses native code to do the fetching.

What would be really useful (in my case at least, where I pre-cache around 1000 images), would be the ability to check if the image is cached, but don't force-cache it as the check happens.

So something like:

// will not trigger image download
const {exists} = CacheManager.getInfo('image-url');

What I'm trying to do is check if all the images are cached, and if not, ask the user if he authorises the app to download the missing images.

Upgrading to the version 4.0.3 error to resolve module

After upgrading the package to the version 4.0.3, i get the following error at starting the packager:

While trying to resolve module react-native-expo-image-cache from file c:\Projects\app\src\components\common\UI\avatar.js, the package c:\Projects\app\node_modules\react-native-expo-image-cache\package.json was successfully found. However, this package itself specifies a main module field that could not be resolved (c:\Projects\app\node_modules\react-native-expo-image-cache\dist\src\index.js. Indeed, none of these files exist

Is this related to the typescript? what should i do? ( i already tried to remove node_modules, reinstall)

Issue with Transparent background

In my list of item, i'm having some PNG files with transparent background such as : Image

Here is the result when i'm using your Image component (even without preview).

It adds a weird shadow effect.

Thanks for your help.

[Unhandled promise rejection: Error: No download object available]

[Unhandled promise rejection: Error: No download object available]

  • node_modules\react-native\Libraries\BatchedBridge\NativeModules.js:123:42 in createErrorFromErrorData
  • node_modules\react-native\Libraries\BatchedBridge\NativeModules.js:80:57 in
  • ... 5 more stack frames from framework internals

image

Updated to the 3.0.1 and got this warning. Previously I was using 2.0.2 and never seen this warning. Did you change somthing in the syntax or the way we have to handle it since the 2.0.2?

Thanks again for your help.

Android crash: Error: socket failed: EMFILE (Too many open files)

In Android production getting the following error resulting in ANR/Crash

Error: unable to open database file (code 2062) ################################################################# Error Code : 2062 (SQLITE_CANTOPEN_EMFILE) Caused By : Application has opened too many files. Maximum of available file descriptors in one process is 1024 in default. (unable to open database file (code 2062)) #################################################################

I think it is unlikely that I actually have 1024 images open at the same time (probably closer to 300). Is there a way to force close files or end the process and start another?

App runs fine in development and for a few minutes in production, but after sufficient browsing, freezes and then if you quit and try and reopen it will not reopen.
Works great on iOS.

Custom cache key

The URL for some of our images contains an auth token that changes periodically - it would be nice if there was a way to specify the cache key separately from the URL. What do you think?

Readme.md: CacheManager.get(uri).cancel() is not a function

I've checked the Readme.md and found that the section about CacheManager might have mistake.
CacheManager section says that it has cancel() method, but CacheManager.get(uri).cancel() throws exception saying it is not a function.

In addition, codes don't include the script of cancel() function.

import {CacheManager} from "react-native-expo-image-cache";

const {uri} = this.props;
const path = CacheManager.get(uri).getPath();
// if path is undefined, the image download has been cancel
CacheManager.get(uri).cancel(); // Cancel image download if one is in progress

TypeScript declaration

Nice component William,

I program using typescript, then I had to make my own "d.ts" script for your components.

Here it is, though pretty simple, hope it's usefull:

## reactNativeExpoImageCache.d.ts

declare module 'react-native-expo-image-cache' {
  import React from "react"
  import { ImageStyle, ViewStyle } from "react-native"

  export function Image(
    style: ViewStyle & ImageStyle,
    preview: string,
    uri: string
  ): React.Component
  
  type Listener = (uri: string) => any

  export class CacheManager {
    static listeners: { [uri: string]: Listener[] }
    static cache: (uri: string, listener: Listener) => Promise<void>
  }

}

[Android] - Image not displayed at full opacity

Version: 1.0.6

The animation bringing the Image to full opacity doesn't seem to start/finish in some cases.

I've notice it happen the first time I load an image (after the app just opened).
If I load another page and reload the page it sometimes work and display the animation at full opacity (anmation appear to be working).
Here how it looks when not properly displayed
image

And here when it's loaded and displayed as it should:
image

I guess, there is a problem with the mounted var you added and the condition.

Method to cancel image downloads?

Hi. Great lib.

I noticed in issue #90 you mentioned that cancel was removed as "it wasn't working as expected with Expo".

Are there provisions to add this back in? It's quite an important aspect of any async request to be able to cancel it.

In my case, I'm making a call in componentDidMount that queries the CacheManager for the path, and sets State. However, the component can be unmounted before the request completes, the instance of CacheManager should cancellable at that point, but currently it's not, and raises the familiar: can't call setState (or forceUpdate) on an unmounted component error.

I understand that the issue is readily resolved with a global property that tracks whether or not the component is unmounted and only calls setState then, but it's quite inelegant.

defaultSource not working as expected

Hi there, first off thanks for this lib. Image caching is a huge issue in RN apps and it's surprising that expo hasn't incorporated something into the core expo modules yet!

Anyways, I have a card component in which this package is being used to render the image.

My use case is the following, I have a remote image url which could be null, so when it is null I'd like to display a fallback image, and from what I can gather I need to use defaultSource for that? Thing is, it just doesn't seem to load the image. My code is as follows:

import { Image as CachedImage } from 'react-native-expo-image-cache';

...

<CachedImage
              style={{
                top: 0,
                left: 0,
                width: '100%',
                height: '100%',
                borderRadius: 4,
                overflow: 'visible',
                resizeMode: 'cover',
                position: 'absolute',
              }}
              resizeMode="cover"
              defaultSource={images.articlePlaceholder}
              uri={event && event.image && event.image.scaled}
            />

Where the placeholder image source is a local image, with require('../path-to-image')

It works fine when there is a url being passed to the uri prop, but not for the local defaultSource. Am I doing something wrong? Any help here would be much appreciated.

clearCache Feature

Sometimes, it happens that while using :

import {Image} from "react-native-expo-image-cache";

const preview = "url_of_my_preview_image.png";
const uri = "url_of_my_full_scaled_image.png";
<Image style={{ height: 100, width: 100 }} {...{preview, uri}} />

It happens sometimes for no reason that my uri is not loaded and only the preview is available. So it renders a blurred image only. (i'm trying my app on three real devices and on iOS simulator when loading 50+ images. Sometimes it happens, most of the time it doesn't.)

Would it be possible to force to remove some URI from the cache so it can be re-uploaded.
An example of implementation, on a flatlist, onRefresh, clean the image Cache and reload the Image. Or inside a Card, add a button reload to force the retrieve of an Image.

Thanks for your help

Update Babel dependencies

Hi,

since the recent upgrade from Expo to SDK31, this package pulls in a lot of older Babel versions.
Are these still needed?

I'll try from a fork to see if this still works with Babel >= 7 and report back here.

Undefined is not an object (evaluating 'this.props.preview') [Android]

image

Thanks for your awesome lib, it works pretty well!

However I get this error sometimes. I'm testing my app super fast, it might be related.
My guess is that the component is maybe removed before download is finished.

I'll dig a little more and let you know if I find something.

Cheers,

Image duplicating

when I put resizeMode='contain' on the component
It works but it also displays the same image as a background to fill the remaining width
<Image
style={{ height: 250, width: Dimensions.get('window').width, backgroundColor: '#ffffff' }}
tint='default'
{...{preview, uri}}
resizeMode='contain'
/>
image

readme update

The readme doesn't list all the props, or functionality that this component accepts/offers.
I nearly overlooked it, thinking it had no onLoad or resizeMode props, till i searched the issues and discovered it handles both excellently, if a little quixotically. Would be a good idea to update :) great work BTW! thank you!

Loading many images at same time / Some other things

Hello!

I have a problem with loading a few hundred images. I have a FlatList with containing scrollviews in each cell that will display the images with horizontal scrolling. When the cache is empty and the app starts, all images begin to load at the same time. Many images fail because of timeout.
I think there must be something like a queue to load the images in batches or so. Any suggestions to improve that?

The other thing I've notice is that it seams that the images starts to load first at the bottom of the list. Why they don't start at the top where the user is look at after start?

An other thing I want to improve is to remove re-rendering. A have a list in grid view style with many images. When I try to add a new item the hole FlatList get refreshed and all images show the preview and load again. What can I do to prevent re-rendering?

I there a way to add an image that is local available to the cache? So that a download of the image is not needed after uploading to the server.

Thanks for your help.

Cache validation and management?

This seem to be a very nice component. I'm studying it to use and want to understand it a little more. In that direction I would be grateful if someone can answer me those two questions:

1 - Is there a way to invalidate cache in the situation I have an image and upload another one to the server with the same name?

2 - Is there a way to clear old unused cached images? Let's say I had some images of elements that are not used anymore. Or that the cache gets full and I need to remove old/unused images.

Image not showing but only preview

Hi,
i made your awesome code works as well, but are 2 days that its not working anymore (dont remember if i updated it).
I can see just the preview, the image no.
Same problem with your example code also.

Any help is appreciated.

Authentication for Images

Hello,

thanks for your work on this library! I'm looking at adding in authentication because my images are behind a protected endpoint - I see that ReactNative has support for passing additional headers via the source param. It appears that this library currently assumes uri is only a string and doesn't have any way to inject additional authentication headers.

I'm looking at implementing that and issuing a PR, but I wanted to check and see if there was either something I was overlooking or any "gotchas" you think I should know about before starting.

Thanks!

[Suggestions] More Usage Example

It would be great to have more usage example about:

  • The CacheManager itself (How & why would we want to use it ourselves ?)
  • What if i don't have base64 image and just thumbnail & image url ?
  • Use it without preview

Feel free to add any other suggestions ๐Ÿ˜„

resizeMode

Hi,
It would be useful to be able to change the resizeMode of the picture.
The 'contain' mode is really usefull for a gallery of different ratio pictures for example. ;-)
Thank you for this simple and strong component !

Add cache support to components without replacing the Image element

Hi,

I'm new to Github so I really don't know yet how to open a branch or pull a request, so I'm posting this idea/contribution here.

Well, as many, I use 3rd party components for my app, and many of those are built around the image component. So in order to make them work with this react-native-expo-image-cache I either have two options:

Option 1: I fork all the 3rd party components I use and replace the image object with this image object.

Option 2: I create a function to make the CacheManager support those components without forking them.

So, being the second option more apealing, I came up with this little function, which should allow me to use the CacheManager within 3rd party components:

// Returns the cached uri for an image, otherwise the fallback uri and triggers cache operation
// stateUri     : set as Control state var where to store the cached uri for the image.
// uri          : the original URI to be/already cached
// fallbackUri  : the URI to return while not yet cached
// listener     : listener that receives the cached URI when obtained and sets stateUri

function uriCache(stateUri: string, uri: string, fallbackUri: string, listener: Listener): string {
  if ((typeof stateUri === 'string') && stateUri)
    return stateUri
  else {
    CacheManager.cache(uri, listener)
  }
  return fallbackUri
}

Usage.....
Let's say I'll use the avatar component from the reac-native-elements library, and wish to cache the picture:


const profileUri = 'https://somewhereInTheWeb/somePic.jpg'
const defaultUri = 'https://somewhereInTheWeb/default.jpg'

class MyView extends React.Component {
  state = {
    cachedUri = undefined
  }
  render = () => (
    <Avatar source = {{
         uri: uriCache( state.cachedUri, profileUri, defaultUri,
                        uri => this.setState({cachedUri: uri}) )
       }}
    />
  }
}

And the same way with any component receiving an URI as parameter.....

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.