React hook for declarative asset loading with automatic state management and error handling. Provides a React-friendly way to load assets with loading states and error reporting.
Downloads and stores one or more assets locally. After the assets are loaded, this hook returns a list of asset instances.
/**
* Downloads and stores one or more assets locally.
* After the assets are loaded, this hook returns a list of asset instances.
* If something went wrong when loading the assets, an error is returned.
*
* Note: The assets are not "reloaded" when you dynamically change the asset list.
*
* @param moduleIds - Single module ID or array of module IDs to load
* @returns Array containing:
* - assets: list of all loaded assets (undefined if not loaded yet)
* - error: error encountered when loading assets (undefined if no error)
*/
function useAssets(moduleIds: number | number[]): [Asset[] | undefined, Error | undefined];Usage Examples:
import React from 'react';
import { Image, ActivityIndicator, Text, View } from 'react-native';
import { useAssets } from 'expo-asset';
// Basic usage with single asset
function SingleAssetComponent() {
const [assets, error] = useAssets(require('./assets/logo.png'));
if (error) {
return <Text>Failed to load asset: {error.message}</Text>;
}
if (!assets) {
return <ActivityIndicator />;
}
return <Image source={assets[0]} style={{ width: 100, height: 100 }} />;
}
// Multiple assets
function MultipleAssetsComponent() {
const [assets, error] = useAssets([
require('./assets/background.jpg'),
require('./assets/icon.png'),
require('./assets/overlay.png')
]);
if (error) {
console.error('Asset loading error:', error);
return <Text>Could not load assets</Text>;
}
if (!assets) {
return <ActivityIndicator size="large" />;
}
const [background, icon, overlay] = assets;
return (
<View>
<Image source={background} style={styles.background} />
<Image source={icon} style={styles.icon} />
<Image source={overlay} style={styles.overlay} />
</View>
);
}
// Conditional rendering based on asset availability
function ConditionalAssetComponent() {
const [assets, error] = useAssets([
require('./assets/image1.png'),
require('./assets/image2.png')
]);
// Handle error state
if (error) {
return (
<View>
<Text>Asset loading failed</Text>
<Text>Error: {error.message}</Text>
</View>
);
}
// Handle loading state
if (!assets) {
return (
<View>
<ActivityIndicator />
<Text>Loading assets...</Text>
</View>
);
}
// Assets loaded successfully
return (
<View>
{assets.map((asset, index) => (
<Image
key={index}
source={asset}
style={{ width: 100, height: 100, margin: 5 }}
/>
))}
</View>
);
}
// Using with asset metadata
function AssetInfoComponent() {
const [assets, error] = useAssets(require('./assets/photo.jpg'));
if (error || !assets) {
return <Text>Loading...</Text>;
}
const [photo] = assets;
return (
<View>
<Image source={photo} style={{ width: 200, height: 200 }} />
<Text>Name: {photo.name}</Text>
<Text>Type: {photo.type}</Text>
<Text>Size: {photo.width} x {photo.height}</Text>
<Text>Downloaded: {photo.downloaded ? 'Yes' : 'No'}</Text>
<Text>Local URI: {photo.localUri}</Text>
</View>
);
}The useAssets hook does not reload assets when the asset list changes dynamically. If you need to load different assets based on state changes, you should use separate hook calls or manage asset loading manually with Asset.loadAsync.
// ❌ This won't reload when selectedAsset changes
function DynamicAssetComponent({ selectedAsset }) {
const [assets, error] = useAssets(selectedAsset);
// Assets won't update when selectedAsset prop changes
}
// ✅ Better approach for dynamic assets
import React, { useState, useEffect } from 'react';
import { Asset } from 'expo-asset';
function DynamicAssetComponent({ selectedAsset }) {
const [asset, setAsset] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
setError(null);
Asset.loadAsync(selectedAsset)
.then(([loadedAsset]) => {
setAsset(loadedAsset);
setLoading(false);
})
.catch(err => {
setError(err);
setLoading(false);
});
}, [selectedAsset]);
if (error) return <Text>Error: {error.message}</Text>;
if (loading) return <ActivityIndicator />;
return <Image source={asset} />;
}Always handle both loading and error states when using useAssets:
function RobustAssetComponent() {
const [assets, error] = useAssets([
require('./assets/required-image.png')
]);
// Always check error state first
if (error) {
console.error('Asset loading failed:', error);
// Show fallback UI or retry mechanism
return <Text>Could not load images</Text>;
}
// Then check loading state
if (!assets) {
return <ActivityIndicator />;
}
// Finally render with loaded assets
return <Image source={assets[0]} />;
}