Closed wagslane closed 3 years ago
Check this out:
import React, { Component } from 'react';
import { View, Image, ImageBackground } from 'react-native';
import * as FileSystem from 'expo-file-system';
import * as Crypto from 'expo-crypto';
export default class CachedImage extends Component {
state = {
imgURI: ''
}
async componentDidMount() {
if (this.props.source.uri) {
const filesystemURI = await this.getImageFilesystemKey(this.props.source.uri);
await this.loadImage(filesystemURI, this.props.source.uri);
}
}
async componentDidUpdate() {
if (this.props.source.uri) {
const filesystemURI = await this.getImageFilesystemKey(this.props.source.uri);
if (this.props.source.uri === this.state.imgURI ||
filesystemURI === this.state.imgURI) {
return null;
}
await this.loadImage(filesystemURI, this.props.source.uri);
}
}
async getImageFilesystemKey(remoteURI) {
const hashed = await Crypto.digestStringAsync(
Crypto.CryptoDigestAlgorithm.SHA256,
remoteURI
);
return `${FileSystem.cacheDirectory}${hashed}`;
}
async loadImage(filesystemURI, remoteURI) {
try {
// Use the cached image if it exists
const metadata = await FileSystem.getInfoAsync(filesystemURI);
if (metadata.exists) {
this.setState({
imgURI: filesystemURI
});
return;
}
// otherwise download to cache
const imageObject = await FileSystem.downloadAsync(
remoteURI,
filesystemURI
);
this.setState({
imgURI: imageObject.uri
});
}
catch (err) {
console.log('Image loading error:', err);
this.setState({ imgURI: remoteURI });
}
}
render() {
let source = this.state.imgURI ? { uri: this.state.imgURI } : null;
if (!source && this.props.source) {
source= this.props.source;
}
return (
<View>
{this.props.isBackground ? (
<ImageBackground
{...this.props}
source={source}
>
{this.props.children}
</ImageBackground>
) : (
<Image
{...this.props}
source={source}
/>
)}
</View>
);
}
}
@charles-goode Sorry could you provide context? There isn't even a diff here
If I understand the issue correctly, you want to be able to also pass app assets to this component perhaps as a local default for an image that may change to a remote URI later? I may have misread this. Do you mean instead to handle image sources retrieved from expo-imagepicker?
Basically we want people to be able to use images that are already local (the same functionality as the RN Image component). The problem right now is that we are still caching those images for no reason and trying to download remote.
If you have a solution please open a PR and tag this issue
As per https://github.com/lane-c-wagner/react-native-expo-cached-image/issues/2#issuecomment-619715528, it is feasible that one would want to use this component to render local images.