200,000+ icons for React Native and Web with platform-aware caching
Traditional icon libraries require you to bundle all icons at build time, leading to:
- ❌ Large bundle sizes (even if you use only 10 icons)
- ❌ Manual imports for each icon
- ❌ Limited icon selection per library
react-native-iconify takes a different approach:
- ✅ 200,000+ icons from 150+ icon sets (Material Design, Feather, Heroicons, Phosphor, Lucide, and more)
- ✅ Load icons by name - no imports needed
- ✅ Zero bundle size impact in development
- ✅ Automatic bundling for production builds
- ✅ Platform-aware caching with SDWebImage (iOS), Glide (Android), and an in-memory web cache
| Feature | Description |
|---|---|
| 🎨 200,000+ Icons | Access to 150+ icon sets from Iconify |
| ⚡ Zero Config | Works out of the box - no manual bundling required |
| 📦 Auto-Bundling | Icons automatically bundled during production builds (APK/IPA) |
| 💾 Native Caching | SDWebImage (iOS) + Glide (Android) for persistent storage |
| 🏗️ New Architecture | Full support for React Native 0.68+ New Architecture |
| 📱 Old Architecture | Backward compatible with React Native 0.60+ |
| 🚀 Expo Support | Works with Expo development builds and EAS |
| 🔧 React Native CLI | Full support for bare React Native projects |
| 🌐 Web Support | Same component and import on React Native Web and Expo Web |
| Platform | Minimum Version |
|---|---|
| React Native | 0.68.0+ |
| React Native (Old Arch) | 0.60.0+ |
| Expo SDK | 49+ |
| React Native Web | 0.19+ |
| iOS | 13.0+ |
| Android | API 21+ (Android 5.0) |
# Using npm
npm install @huymobile/react-native-iconify react-native-svg
# Using yarn
yarn add @huymobile/react-native-iconify react-native-svg
# Using pnpm
pnpm add @huymobile/react-native-iconify react-native-svg
# Using bun
bun add @huymobile/react-native-iconify react-native-svgcd ios && pod installnpx expo install react-native-svg
npx expo prebuildNote: react-native-iconify requires a development build. It will not work with Expo Go.
This native-build requirement applies to iOS and Android. Expo Web uses the JavaScript in-memory cache and does not load a native cache module.
import React from 'react';
import { View } from 'react-native';
import { IconifyIcon } from '@huymobile/react-native-iconify';
export default function App() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
{/* Material Design Icons */}
<IconifyIcon name="mdi:home" size={32} color="#333" />
{/* Heroicons */}
<IconifyIcon name="heroicons:user-solid" size={32} color="blue" />
{/* Feather Icons */}
<IconifyIcon name="feather:settings" size={32} color="green" />
{/* Phosphor Icons */}
<IconifyIcon name="ph:heart-fill" size={32} color="red" />
</View>
);
}Browse and search icons at icon-sets.iconify.design
Icon names follow the format: {prefix}:{icon-name}
Examples:
mdi:home- Material Design Iconsheroicons:user- Heroiconsfeather:settings- Feather Iconslucide:camera- Lucide Iconsph:heart- Phosphor Icons
| Prop | Type | Default | Description |
|---|---|---|---|
name |
string |
required | Icon name in format prefix:name |
size |
number |
24 |
Icon size (width & height) |
color |
string |
#000 |
Icon color |
rotate |
number |
0 |
Rotation in degrees |
flip |
'horizontal' | 'vertical' | 'both' |
- | Flip the icon |
style |
ViewStyle |
- | Additional styles |
onLoad |
() => void |
- | Called when icon loads successfully |
onError |
(error: Error) => void |
- | Called when icon fails to load |
fallback |
ReactNode |
- | Fallback component while loading |
testID |
string |
- | Test ID for testing |
// Basic usage
<IconifyIcon name="mdi:home" size={24} color="blue" />
// With rotation
<IconifyIcon name="mdi:arrow-right" size={24} rotate={90} />
// With flip
<IconifyIcon name="mdi:arrow-left" size={24} flip="horizontal" />
// With custom fallback
<IconifyIcon
name="mdi:home"
size={24}
fallback={<ActivityIndicator size="small" />}
/>
// With callbacks
<IconifyIcon
name="mdi:home"
size={24}
onLoad={() => console.log('Icon loaded!')}
onError={(err) => console.error('Failed:', err)}
/>Release builds run scripts/scan-icons.js over your source tree and bundle every icon it
finds, so those icons render instantly and work offline. You can run the same scan yourself:
node node_modules/@huymobile/react-native-iconify/scripts/scan-icons.jsIcons are detected through your own wrapper components, not only through IconifyIcon
directly. A component that renders IconifyIcon and forwards name is followed
automatically, up to three levels deep:
// components/AppIcon.tsx - detected as a wrapper
export default function AppIcon({ name, size = 24, ...rest }: AppIconProps) {
return <IconifyIcon name={name} size={size} {...rest} />;
}
// screens/HomeScreen.tsx - "mdi:heart" is bundled
<AppIcon name="mdi:heart" />Only complete names can be bundled, but they are found in three ways, not one:
- Component scan —
<IconifyIcon name="mdi:home" />and usages through wrappers. - Expression literals —
name={active ? 'mdi:check' : 'mdi:close'}bundles both branches. A string only counts when its prefix is a real Iconify collection, so an i18n key likename={t('common:back')}is never mistaken for an icon. - Literal scan (the same strategy Tailwind uses for class names) — any icon-shaped
string literal anywhere in the scanned files, e.g. a
constants/icons.tsmap that imports nothing. A candidate must pass three filters before it is bundled: theprefix:icon-nameshape, a known collection prefix (scripts/iconify-prefixes.json, refresh withnode scripts/update-prefixes.js), and existence — the Iconify API drops names it does not know at fetch time. A false positive costs a few hundred bytes in the bundle; a false negative costs one runtime fetch.
A name built at runtime — name={iconName}, name={`mdi:${kind}`} — cannot be
resolved by any static scan. It is reported at the end of the scan with its file and
line, and is fetched from the Iconify API at runtime instead. As with Tailwind class
names: write complete icon names, or safelist them.
The safelist lives in your app's package.json. Entries containing * are globs,
expanded against the collection's icon list at build time — the right tool for
name={`mdi:weather-${condition}`}:
{
"iconify": {
"icons": ["mdi:check", "mdi:weather-*"],
"components": ["LegacyIcon"],
"detection": "smart",
"extraPrefixes": ["my-custom-set"],
"exclude": ["carbon:user"]
}
}| Field | Description |
|---|---|
icons |
Extra icon names to bundle. * globs are expanded against the collection at build time |
components |
Extra component names to scan, for wrappers the scanner does not reach |
detection |
"smart" (default) enables the literal tiers; "strict" restricts bundling to the component scan |
extraPrefixes |
Additional collection prefixes to accept, for self-hosted icon sets |
exclude |
Names or glob patterns to keep out of the bundle, e.g. a false positive from the literal scan |
react-native-iconify supports 150+ icon sets with over 200,000 icons.
| Icon Set | Prefix | Icons | License |
|---|---|---|---|
| Material Design Icons | mdi |
7,000+ | Apache 2.0 |
| Heroicons | heroicons |
290+ | MIT |
| Feather Icons | feather |
280+ | MIT |
| Phosphor | ph |
7,000+ | MIT |
| Lucide | lucide |
1,400+ | ISC |
| Tabler Icons | tabler |
4,400+ | MIT |
| Bootstrap Icons | bi |
1,900+ | MIT |
| Font Awesome | fa6-solid |
1,400+ | CC BY 4.0 |
| Remix Icons | ri |
2,700+ | Apache 2.0 |
| Carbon | carbon |
2,000+ | Apache 2.0 |
Browse all icon sets at icon-sets.iconify.design
react-native-iconify fully supports React Native's New Architecture:
- ✅ TurboModules for native cache access
- ✅ Fabric-compatible rendering
- ✅ Concurrent features support
Backward compatible with the bridge-based architecture:
- ✅ Works with React Native 0.60+
- ✅ Standard Native Modules
- ✅ Full feature parity
# Install
npx expo install @huymobile/react-native-iconify react-native-svg
# Create development build
npx expo prebuild
npx expo run:ios
# or
npx expo run:android# Build for production
eas build --platform all
⚠️ Not Supported: react-native-iconify requires native modules and will not work with Expo Go. Use a development build instead.
React Native Web and Expo Web use the same component and import as iOS and
Android—an app-level .web.tsx wrapper is not required:
import { IconifyIcon } from '@huymobile/react-native-iconify';
export function AppIcon() {
return <IconifyIcon name="mdi:web" size={32} color="#2563eb" />;
}Web caching is in memory and resets when the page reloads. iOS and Android continue to use their persistent native cache backends.
| Scenario | Load Time |
|---|---|
| Bundled icon (production) | 0ms |
| Native cache hit | 15-35ms |
| Web memory cache hit | <1ms |
| API fetch (first load) | 200-500ms |
- Check internet connection (for API fetches)
- Verify icon name format:
prefix:icon-name - Check if icon exists at icon-sets.iconify.design
cd ios && pod install --repo-updatecd android && ./gradlew cleannpx react-native start --reset-cache- Iconify - The universal icon framework
- react-native-svg - SVG rendering for React Native
- SDWebImage - iOS image caching
- Glide - Android image caching