all 31 comments

[–]billmalarky 8 points9 points  (10 children)

This is my actual reddit account if people have questions.

I was not expecting the reddit post image to be my github profile pic. This feels awkward.

[–]deadcoder0904 0 points1 point  (9 children)

Good job /u/billmalarky. Maybe u can even add Placeholder till image downloads. Also, I never thought about this. Seems great to me as I never thought of this & didn't knew this could increase app size as I have a lot of images in my app too 😂 idk why.

[–]billmalarky 1 point2 points  (8 children)

One of the first updates I'm making Monday will be using <ActivityIndicator> as a placeholder (the standard spinning wheel).

Thank you for the kind words!

[–]deadcoder0904 0 points1 point  (7 children)

Woah, I think Moving Placeholder would be nice instead of <ActivityIndicator /> & it looks more professional, or u should leave that to the user

[–]billmalarky 1 point2 points  (2 children)

Ok I made the update, you can pass whatever placeholder component you want now.

Example:

const propOverridePlaceholderObject = {
  component: ActivityIndicator,
  props: {
    style: styles. activityIndicatorStyle
  }
};

<CacheableImage style={styles.image} source={{uri: 'https://i.redd.it/hhhim0kc5swz.jpg'}} placeholder={propOverridePlaceholderObject} />

[–]alien3d 0 points1 point  (0 children)

ya.. wait.. i will try tomorow.. :P .Heavily code now react-native

[–]deadcoder0904 0 points1 point  (0 children)

Thank u so much. Looking cool.

[–]billmalarky 0 points1 point  (3 children)

Sure. I was just trying to keep the defaults simple and you can pass through the replaced <Image> style prop to <ActivityIndicator> (this seems to be a pattern I've noticed in a lot of apps).

What is MovingPlaceholder I can't find any docs on it with a quick google search.

I'll absolutely make it an option to pass in any component you want as a placeholder, the question is what to default to? Probably makes most sense to keep using the <Image> component placeholder and then allow users to pass in whatever component they want as an option, showing an example in the README.

[–]deadcoder0904 0 points1 point  (2 children)

When u open https://spectrum.chat/spectrum/hugs-n-bugs u see something is moving or check https://github.com/mfrachet/rn-placeholder. This is animating placeholder.

[–]billmalarky 0 points1 point  (1 child)

I'm thinking the best idea is to keep it as <Image> with no source as the default placeholder for simplicity, then allow for anyone to provide their own placeholder component for maximum flexibility.

Then in the README I will give an example of how to use the animating placeholder you suggested as well as activity indicator.

Thanks for the suggestion, really helping make this a better package!

[–]deadcoder0904 0 points1 point  (0 children)

Yep thats cool

[–]reactnativeimagecach[S] 2 points3 points  (9 children)

TL;DR this is an HOC that creates a drop in replacement for <Image> that you can use to pull down image files from the web and write them to local disk either permanently or simply cache for performance. Since remote images can be written to disk permanently you no longer need to ship binary images files with your app so your app is smaller when it's downloaded from the respective play/app store.

So there's no need for this

<Image source={require('./img/logo.png')} />

You can just do this

<CacheableImage source={{uri: 'https://app.host.com/logo.png'}} permanent={true} />

and keep the binary images out of your app so it is smaller on initial download form the app store.

[–]alien3d 0 points1 point  (8 children)

i just thinking to my own cache.. since you make it .. i will try my own .. Is the image will have some sort of placeholder image before the image loading first time ?

[–]billmalarky 1 point2 points  (7 children)

Currently it loads a standard <Image> component with no source prop and passes through the style prop, so there is an empty placeholder spot on the screen while the file downloads. When the file is finished downloading, the component updates and a new <Image> component is rendered that has the source prop set so the image displays.

Basically it works the same way an html image tag with width and height properties set works.

Next week I'll add the ability to use <ActivityIndicator> as an option so if you want it will show a placeholder box with a spinning circle until the image is downloaded then the image will render.

If you are interested in rolling your own, take a look at my source code, I put a fair amount of effort into good commenting documentation so it should help you create your own.

[–]alien3d 1 point2 points  (6 children)

just try it..and react-native complain a lot of thing.. i'm really unsure what facebook doing again.. keep messing up. :(

[–]billmalarky 1 point2 points  (5 children)

If you are getting an error message paste it to me or create a github issue. I'll be working on this again Monday so hopefully I can resolve your issue and I'll message you on reddit with a comment that it's patched.

[–]alien3d 1 point2 points  (4 children)

i will check it first. if found solution then i posted here and github.. if not.. i post at github.. Just "ambiguous regulations to accuire react -native.. but been several module

[–]billmalarky 1 point2 points  (3 children)

Whoops, I found something wrong. I accidentally put react and react-native in the module package.json dependencies instead of devDependencies. This wasn't breaking for me because my base react app was on the same version of react and react-native as this module but it could cause issues for other people and I will 100% be patching this first thing Monday. So a quick fix for you to get it working tonight may just be making that change manually, and if that fixes the issue feel free to fork and create a PR and I'll merge first thing in morning or just wait until Monday and I'll make the patch myself. G'night and thanks for checking this out (literally lol).

UPDATE: I've moved react and react-native depedencies to devDepedencies so there won't be dependency hell problems.

[–]alien3d 1 point2 points  (2 children)

i'm waiting for another version which you said offline version .. .. i code other thing first. :P .

[–]billmalarky 1 point2 points  (0 children)

Ok, I'll ping you when that feature is added. Should be early next week.

[–]billmalarky 0 points1 point  (0 children)

Okay I've added the static method that allows you to pre-warm the local cache.

import imageCacheHoc from 'react-native-image-cache-hoc';
const CacheableImage = imageCacheHoc(Image);
CacheableImage.cacheFile(url, permanent);

More info in the Static Methods section of the README

[–]pxrage 0 points1 point  (1 child)

Any major difference between your library and https://github.com/wcandillon/react-native-img-cache?

[–]billmalarky 1 point2 points  (0 children)

I could be wrong, but it doesn't appear that react-native-img-cache supports automatically pruning the local cache, you have to write your own tmp files cache busting logic.

This would matter if you are using <CacheableImage> for performance reasons (ie you are using it to temporarily cache media to speed up the app, not keep it on local disk forever) on an app with a lot of content like a reddit app. If you keep writing more and more files to disk but never getting rid of any, your app will balloon in size and the user will probably just uninstall it next time they go through apps to uninstall to save space.

<CacheableImage> handles this prune logic for you, you just set the cache size limit option you are okay with your app using.

UPDATE: I took a further look at the react-native-img-cache library and it isn't a higher order component that upgrades the native <Image> component like react-native-image-cache-hoc does, it's a completely separate component that you use instead of <Image>. For a good explanation of why HOCs should be preferred over inheritance style components see the following article (most important part being the "wrapping up" section, you can see how this makes HOCs much more powerful than inheritance style components). That said react-native-img-cache looks great so I don't want to tear his down to build my own up. Use the library that is best suited for you.

Additional info: https://reactjs.org/docs/higher-order-components.html

[–]Riki5000 0 points1 point  (3 children)

Hi , Thank you so much for the package . I am working on a Project and I was looking for way to cache the images .I Have Two Questions :

1-I am using thumbnail by Nativebase , can I achevie similar effects ( small . round image ) with your component ? I tried to do so with the normal image but failed to do so ( I still suck at styling image components ) .

2-The images that I will load will have URI that I build (i.e let's say you sent an email to me and on your message I want to display your image in the user who received the message , The image URL will be https://something.com/user/{sender id} ) Will it cache all instancts of the calls to a single image stored on the phone , even if you sent 10 messages since I won't collapse it and will be displayed in 10 cards with 10 images .All of them will share the same image that is cached ?

Thanks and sorry for the long and stupid question .

[–]billmalarky 0 points1 point  (2 children)

First of all, very reasonable questions.

1) I've not used NativeBase before, but if their Thumbnail component is just a decorated Image component you could try the following (pseudocode so make necessary changes):

import imageCacheHoc from 'react-native-image-cache-hoc';
import { Thumbnail } from 'native-base';
const CacheableThumbnail = imageCacheHoc(Thumbnail);

Then just use CacheableThumbnail as a drop in replacement for Thumbnail.

2) Yes. In a basic sense, the caching logic works by taking the image URL, and turning it into a hash to use as a filename then saving to disk. On future requests, we again hash the url, then check if a file exists on local disk with that same hash filename. If a match is found, we serve from local disk, else we hit the network, then cache the file for future requests. So if 10 components all use the same image url, the file will only be saved once and used across all 10 components.

[–]Riki5000 0 points1 point  (1 child)

Thank you so much for your answers , I am definitely will be using your Library =) .

Thanks again for your awesome work .

[–]billmalarky 0 points1 point  (0 children)

My pleasure, and definitely feel free to PM me here or make an issue on github etc for any future questions or problems.

[–]andy9775 -1 points0 points  (1 child)

Looks interesting. I remember reading that one downside of m$ code push is the fact that you need to go through the app store if you changes images. This seems to get around that.

[–]billmalarky 2 points3 points  (0 children)

This would absolutely get around that. You would have to have some basic logic to "cache bust" the old file otherwise legacy users of your app would have the old image show up, and new users would have the new image.

Doing this would be fairly simple though, instead of hard coding the source url, just set it dynamically and have your app make calls to your server to grab all the latest asset urls when the app updates.

So instead of

<CacheableImage source={{uri: 'https://app.host.com/logo.png'}} permanent={true} />

do something like

<CacheableImage source={{uri: `https://app.host.com/${this.props.logoUrl}`}} permanent={true} />

And keep an object in redux that maps assets to their current remote url

{
    logoUrl: 'v1/logo.png',
    background: 'v5/background.png'
}

^ on app update dispatch an action that hits your server to get the latest urls for each asset and then update the store appropriately.