'Caching images in expo is thowing Failed to load assets error in production
This is my code to cache all the images in my local folder. I'm prefetching all the images and after that resolving the promise. But this always results in "Failed to load all assets" error in Expo production mode.
function cacheImages(images) {
return images.map((image) => {
if (typeof image === "string") {
return Image.prefetch(image);
} else {
return Asset.fromModule(image).downloadAsync();
}
});
}
async function _loadAssetsAsync() {
try {
imageAssets = cacheImages([
require("./ASSETS/Mariodimarko.jpg"),
require("./ASSETS/SAMMY_WFX.jpg"),
]);
await Promise.all([...imageAssets]);
} catch (error) {
console.warn(error);
await Promise.all([...imageAssets]);
}
}
return ready? (
<NavigationContainer>
<AuthProvider>
<StackNavigator />
</AuthProvider>
</NavigationContainer>
) : (
<AppLoading
startAsync={_loadAssetsAsync}
onFinish={() => setReady(true)}
onError={(error) => console.warn(error)}
/>
);
Solution 1:[1]
You are not defining your imageAssets or if you did out of the function, probably it was defined as const. This is generating an exception catched by your code.
Just add the keyword const before imageAssets
...
try {
const imageAssets = cacheImages([
require("./ASSETS/Mariodimarko.jpg"),
require("./ASSETS/SAMMY_WFX.jpg"),
]);
await Promise.all([...imageAssets]);
} catch (error) {
console.warn(error);
await Promise.all([...imageAssets]);
}
...
Solution 2:[2]
If your paths to the images really exists, the only reason that i can imagine is due the dev enviroment. Let's try this:
const cacheImages = (images) => {
return images.map(image => {
if (typeof image === 'string') {
return Image.prefetch(image);
} else {
return Asset.fromModule(image).downloadAsync();
}
});
};
const _loadAssetsAsync = async() => {
const myImages = {
a1: { asset: require("./ASSETS/Mariodimarko.jpg") },
a2: { asset: require("./ASSETS/SAMMY_WFX.jpg") },
};
let arrayImages = [], assetInfo;
for (const key in myImages) {
assetInfo = await Asset.fromModule(myImages[key].asset);
console.log(assetInfo); // just for you see the info
if ( ( assetInfo.dowloaded ) && ( assetInfo.localUri !== null ) ) {
/* this never happens in development mode even you
added the path to your app.json (assetBundlePatterns)
and if it was previously downloaded in production mode,
you dont need to download it again,right?
*/
}
else {
/* here we add the remote url to the arrayImages */
arrayImages.push(assetInfo.uri);
}
};
if ( arrayImages.length > 0 ){
const imageAssets = cacheImages(arrayImages);
try { await Promise.all([...imageAssets]);}
catch (error) { console.warn(error); }
}
};
const [ready, setReady] = useState(false);
if (ready) {
return (
<NavigationContainer>
<AuthProvider>
<StackNavigator />
</AuthProvider>
</NavigationContainer>
);
} else {
return (
<AppLoading
startAsync={_loadAssetsAsync}
onFinish={() => setReady(true)}
onError={(error) => console.warn(error)}
/>
);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Sylvio Ruiz Neto |
Solution 2 | Sylvio Ruiz Neto |