Skip to content

Instantly share code, notes, and snippets.

@tomasswood
Created December 29, 2021 22:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomasswood/08502e5a29974e48b6772956632dd34e to your computer and use it in GitHub Desktop.
Save tomasswood/08502e5a29974e48b6772956632dd34e to your computer and use it in GitHub Desktop.
React Native / Expo Fast Cached Image
import React, { useEffect, useState } from 'react';
import { Image, ImageProps, ImageURISource } from 'react-native';
import * as FileSystem from 'expo-file-system';
import * as Crypto from 'expo-crypto';
const getImageFileSystemKey = async (remoteURI: string) => {
const fileHash = await Crypto.digestStringAsync(Crypto.CryptoDigestAlgorithm.SHA256, remoteURI);
return `${FileSystem.cacheDirectory}${fileHash}`;
};
type CachedImageProps = Omit<ImageProps, 'source'> & {
source: ImageURISource;
};
const CachedImage = (props: CachedImageProps) => {
const [imgSource, setImgSource] = useState<ImageURISource>({});
useEffect(() => {
if (props.source?.uri && props.source.uri !== imgSource.uri) {
getImageFileSystemKey(props.source.uri).then(async (fileSystemURI: string) => {
if (!props.source?.uri || props.source.uri === imgSource.uri || fileSystemURI === imgSource.uri) {
return null;
}
const remoteURISource = props.source;
try {
// Check the cached image exists
const cachedFileData = await FileSystem.getInfoAsync(fileSystemURI);
if (cachedFileData.exists) {
setImgSource({ uri: fileSystemURI });
return;
}
// Download the remote image to the file cache
const imageObject = await FileSystem.downloadAsync(remoteURISource.uri, fileSystemURI);
setImgSource(imageObject);
} catch (error) {
// Fallback to the remote image
setImgSource(remoteURISource);
}
});
}
}, [imgSource, props.source?.uri]);
return <Image {...props} style={props.style} source={imgSource} />;
};
export default CachedImage;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment