react-native-expo-image-cache icon indicating copy to clipboard operation
react-native-expo-image-cache copied to clipboard

Add cache support to components without replacing the Image element

Open Piropa opened this issue 6 years ago • 3 comments

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.....

Piropa avatar Mar 05 '18 23:03 Piropa

Another application could be when you need to wait for the Cached URI straightforward, then, this function could solve that situation:

  const getCachedUri = (uri: string): Promise<string> => new Promise (resolve => {
    const listener = (uri: string) => resolve (uri)
    CacheManager.cache(uri, listener)
  })

usage:

const someImageUri = 'https://somewhereInTheWeb/somePic.jpg'
let cachedUri = await getCachedUri(someImageUri)

or, in case I have an array of images:

const someUriArray = ['https://somewhereInTheWeb/somePic.jpg', 
                      'https://somewhereInTheWeb/anotherPic.jpg', 
                      'https://somewhereInTheWeb/yetAnotherPic.jpg']

let newCachedArray = someUriArray.map(uri => await getCachedUri(uri))

But i'm just not sure about this last form might solve the problem for image arrays properly.

Piropa avatar Mar 06 '18 02:03 Piropa

@Piropa Is it possible that what you are looking for is to pass a custom component that will replace the default which is <Image> from React Native. For example:

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

const preview = "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}} component={Avatar} />

If this is what you are looking for, we can introduce it.

wcandillon avatar Mar 07 '18 07:03 wcandillon

Thank you wCandillon,

It's an interesting proposal, haven't thought it that way. It will work for simple-uri image components that use source as it's data source and that source is a simple uri.

Good,

Piropa avatar Mar 07 '18 20:03 Piropa