# Asset Management
## Folder Structure
```
src/assets/
├── images/
│ ├── logo.png
│ ├── logo@2x.png
│ └── logo@3x.png
├── icons/
│ └── index.ts
└── fonts/
├── Montserrat-Regular.ttf
└── Montserrat-Bold.ttf
```
## Image Management
**Create image index file:**
```typescript
// src/assets/images/index.ts
export const Images = {
logo: require('./logo.png'),
splash: require('./splash.png'),
placeholder: require('./placeholder.png'),
// Add more images here
};
```
**Usage in components:**
```typescript
import {Images} from '@assets/images';
import {Image} from 'react-native';
const MyComponent = () => (
);
```
## Icon Management
**Install react-native-vector-icons:**
```bash
yarn add react-native-vector-icons
yarn add -D @types/react-native-vector-icons
# iOS setup
cd ios && pod install
```
**Create icon component:**
```typescript
// src/components/common/Icon/Icon.tsx
import React from 'react';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import Ionicons from 'react-native-vector-icons/Ionicons';
import FontAwesome from 'react-native-vector-icons/FontAwesome';
type IconFamily = 'MaterialIcons' | 'Ionicons' | 'FontAwesome';
interface IconProps {
name: string;
size?: number;
color?: string;
family?: IconFamily;
}
const IconComponents = {
MaterialIcons,
Ionicons,
FontAwesome,
};
export const Icon: React.FC = ({
name,
size = 24,
color = '#000',
family = 'MaterialIcons',
}) => {
const IconComponent = IconComponents[family];
return ;
};
```
## SVG Icons
**Install react-native-svg:**
```bash
yarn add react-native-svg
yarn add -D @types/react-native-svg
# iOS setup
cd ios && pod install
```
**Create SVG icon component:**
```typescript
// src/components/common/SvgIcon/SvgIcon.tsx
import React from 'react';
import Svg, {Path, Circle, Rect} from 'react-native-svg';
interface SvgIconProps {
name: string;
size?: number;
color?: string;
}
const iconPaths = {
home: 'M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z',
user: 'M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z',
// Add more icon paths
};
export const SvgIcon: React.FC = ({
name,
size = 24,
color = '#000',
}) => {
const path = iconPaths[name as keyof typeof iconPaths];
if (!path) {
console.warn(`Icon "${name}" not found`);
return null;
}
return (
);
};
```
## Image Optimization
**Install react-native-fast-image:**
```bash
yarn add react-native-fast-image
# iOS setup
cd ios && pod install
```
**Optimized image component:**
```typescript
// src/components/common/OptimizedImage/OptimizedImage.tsx
import React from 'react';
import FastImage, {FastImageProps} from 'react-native-fast-image';
import {StyleSheet, View, ActivityIndicator} from 'react-native';
interface OptimizedImageProps extends FastImageProps {
showLoader?: boolean;
loaderColor?: string;
}
export const OptimizedImage: React.FC = ({
showLoader = true,
loaderColor = '#007AFF',
style,
...props
}) => {
const [loading, setLoading] = React.useState(true);
return (
setLoading(true)}
onLoadEnd={() => setLoading(false)}
resizeMode={FastImage.resizeMode.cover}
/>
{loading && showLoader && (
)}
);
};
const styles = StyleSheet.create({
loader: {
...StyleSheet.absoluteFillObject,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.1)',
},
});
```
## Asset Preloading
```typescript
// src/utils/assetPreloader.ts
import {Image} from 'react-native';
import {Images} from '@assets/images';
export const preloadImages = async (): Promise => {
const imagePromises = Object.values(Images).map(image => {
return new Promise((resolve, reject) => {
Image.prefetch(Image.resolveAssetSource(image).uri)
.then(() => resolve())
.catch(reject);
});
});
try {
await Promise.all(imagePromises);
console.log('All images preloaded successfully');
} catch (error) {
console.error('Error preloading images:', error);
}
};
```
## Image Caching Strategy
```typescript
// src/utils/imageCache.ts
import AsyncStorage from '@react-native-async-storage/async-storage';
import RNFS from 'react-native-fs';
const CACHE_DIR = `${RNFS.CachesDirectoryPath}/images`;
const CACHE_KEY_PREFIX = 'image_cache_';
export class ImageCache {
static async getCachedImagePath(url: string): Promise {
try {
const cacheKey = `${CACHE_KEY_PREFIX}${this.hashUrl(url)}`;
const cachedPath = await AsyncStorage.getItem(cacheKey);
if (cachedPath && await RNFS.exists(cachedPath)) {
return cachedPath;
}
return null;
} catch (error) {
console.error('Error getting cached image:', error);
return null;
}
}
static async cacheImage(url: string): Promise {
try {
const fileName = this.hashUrl(url);
const filePath = `${CACHE_DIR}/${fileName}`;
const cacheKey = `${CACHE_KEY_PREFIX}${fileName}`;
// Ensure cache directory exists
await RNFS.mkdir(CACHE_DIR);
// Download and cache the image
await RNFS.downloadFile({
fromUrl: url,
toFile: filePath,
}).promise;
// Store the path in AsyncStorage
await AsyncStorage.setItem(cacheKey, filePath);
return filePath;
} catch (error) {
console.error('Error caching image:', error);
throw error;
}
}
private static hashUrl(url: string): string {
// Simple hash function for URL
let hash = 0;
for (let i = 0; i < url.length; i++) {
const char = url.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash; // Convert to 32-bit integer
}
return Math.abs(hash).toString();
}
}
```