Skip to content

Instantly share code, notes, and snippets.

@brentvatne
Created April 26, 2018 18:58
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brentvatne/51da088ffaf11d4f60b9e5c4ff2bacd4 to your computer and use it in GitHub Desktop.
Save brentvatne/51da088ffaf11d4f60b9e5c4ff2bacd4 to your computer and use it in GitHub Desktop.
import React from 'react';
import { Image, View, StyleSheet } from 'react-native';
import { Asset, FileSystem } from 'expo';
import sha256 from 'crypto-js/sha256';
export default class CachedImage extends React.Component {
state = {
source: null,
};
async componentDidMount() {
let source = this.props.source;
try {
if (typeof source === 'number') {
await Asset.fromModule(source).downloadAsync();
} else if (source && source.uri) {
let parts = source.uri.split('.');
let ext = parts[parts.length - 1];
let name = sha256(source.uri);
let filepath = `${FileSystem.documentDirectory}${name}.${ext}'`;
let { exists } = await FileSystem.getInfoAsync(filepath);
if (exists) {
source = { uri: filepath };
} else {
let { uri } = await FileSystem.downloadAsync(source.uri, filepath);
source = { uri };
}
}
} catch (e) {
console.log(e);
} finally {
this.setState({ source });
}
}
render() {
if (this.state.source) {
return <Image {...this.props} source={this.state.source} />;
} else {
let safeImageStyle = { ...StyleSheet.flatten(this.props.style) };
delete safeImageStyle.tintColor;
delete safeImageStyle.resizeMode;
return <View style={safeImageStyle} />;
}
}
}
@azizvc
Copy link

azizvc commented Jun 17, 2020

Thank you, your code helped me a lot.
Here is a version that was work for me, with updates for newer version of expo

import React from 'react';
import { Image, View, StyleSheet } from 'react-native';
import { Asset } from 'expo';
import * as FileSystem from 'expo-file-system';
import sha256 from 'crypto-js/sha256';

export default class CachedImage extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			source: null,
		};
	}

	async componentDidMount() {
		let { source } = this.props;

		try {
			if (typeof source === 'number') {
				await Asset.fromModule(source).downloadAsync();

			} else if (source && source.uri) {
				const parts = source.uri.split('.');
				const ext = parts[parts.length - 1];
				const name = sha256(source.uri);
				const filepath = `${FileSystem.cacheDirectory}${name}.${ext}'`;
				const { exists } = await FileSystem.getInfoAsync(filepath);
				if (exists) {
					source = { uri: filepath };
				} else {
					const { uri } = await FileSystem.downloadAsync(source.uri, filepath);
					source = { uri };
				}
			}
		} catch (e) {
			console.log(e);
		} finally {
			this.setState({ source });
		}
	}

	render() {
		const { source } = this.state;
		const { style } = this.props;

		if (source) {
			return <Image {...this.props} source={source} />;
		}

		const safeImageStyle = { ...StyleSheet.flatten(style) };
		delete safeImageStyle.tintColor;
		delete safeImageStyle.resizeMode;
		return <View style={safeImageStyle} />;
	}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment