Skip to main content

React Navigation

rn-iconify provides helpers for seamless integration with React Navigation.

Tab Navigatorโ€‹

Use createTabBarIcon for bottom tab navigation:

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createTabBarIcon } from 'rn-iconify';

const Tab = createBottomTabNavigator();

function TabNavigator() {
return (
<Tab.Navigator>
<Tab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarIcon: createTabBarIcon('mdi:home'),
}}
/>
<Tab.Screen
name="Search"
component={SearchScreen}
options={{
tabBarIcon: createTabBarIcon('heroicons:magnifying-glass'),
}}
/>
<Tab.Screen
name="Profile"
component={ProfileScreen}
options={{
tabBarIcon: createTabBarIcon('mdi:account'),
}}
/>
</Tab.Navigator>
);
}

Tab Icon Optionsโ€‹

Customize tab icons with additional options:

<Tab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarIcon: createTabBarIcon({
focused: 'mdi:home',
unfocused: 'mdi:home-outline',
size: 28,
}),
}}
/>

Drawer Navigatorโ€‹

Use createDrawerIcon for drawer navigation:

import { createDrawerNavigator } from '@react-navigation/drawer';
import { createDrawerIcon } from 'rn-iconify';

const Drawer = createDrawerNavigator();

function DrawerNavigator() {
return (
<Drawer.Navigator>
<Drawer.Screen
name="Home"
component={HomeScreen}
options={{
drawerIcon: createDrawerIcon('mdi:home'),
}}
/>
<Drawer.Screen
name="Settings"
component={SettingsScreen}
options={{
drawerIcon: createDrawerIcon('mdi:cog'),
}}
/>
<Drawer.Screen
name="Help"
component={HelpScreen}
options={{
drawerIcon: createDrawerIcon('mdi:help-circle'),
}}
/>
</Drawer.Navigator>
);
}

Header Iconsโ€‹

Use createHeaderIcon for navigation header buttons:

import { createHeaderIcon } from 'rn-iconify';

function DetailsScreen({ navigation }) {
return (
<Stack.Screen
name="Details"
component={DetailsContent}
options={{
headerRight: createHeaderIcon({
icon: 'mdi:dots-vertical',
onPress: () => console.log('Menu pressed'),
}),
headerLeft: createHeaderIcon({
icon: 'mdi:arrow-left',
onPress: () => navigation.goBack(),
}),
}}
/>
);
}

Header Icon Optionsโ€‹

createHeaderIcon({
// Icon name (required)
icon: 'mdi:menu',

// Press handler
onPress: () => {},

// Custom size (default: 24)
size: 24,

// Custom color (overrides theme)
color: '#333',

// Accessibility label
accessibilityLabel: 'Open menu',

// Hit slop for easier tapping
hitSlop: { top: 10, bottom: 10, left: 10, right: 10 },
})

Complete Exampleโ€‹

Full navigation setup with rn-iconify:

import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { IconThemeProvider, createTabBarIcon, createHeaderIcon } from 'rn-iconify';

const Tab = createBottomTabNavigator();
const Stack = createNativeStackNavigator();

function HomeStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="HomeMain"
component={HomeScreen}
options={({ navigation }) => ({
headerRight: createHeaderIcon({
icon: 'mdi:bell',
onPress: () => navigation.navigate('Notifications'),
}),
})}
/>
<Stack.Screen name="Details" component={DetailsScreen} />
<Stack.Screen name="Notifications" component={NotificationsScreen} />
</Stack.Navigator>
);
}

function App() {
return (
<IconThemeProvider theme={{ size: 24 }}>
<NavigationContainer>
<Tab.Navigator
screenOptions={{
tabBarActiveTintColor: '#6366f1',
tabBarInactiveTintColor: '#9ca3af',
}}
>
<Tab.Screen
name="Home"
component={HomeStack}
options={{
headerShown: false,
tabBarIcon: createTabBarIcon('mdi:home'),
}}
/>
<Tab.Screen
name="Search"
component={SearchScreen}
options={{
tabBarIcon: createTabBarIcon('mdi:magnify'),
}}
/>
<Tab.Screen
name="Profile"
component={ProfileScreen}
options={{
tabBarIcon: createTabBarIcon('mdi:account'),
}}
/>
</Tab.Navigator>
</NavigationContainer>
</IconThemeProvider>
);
}

With Icon Aliasesโ€‹

Combine with icon aliases for cleaner code:

import { createIconAliases, createTabBarIcon } from 'rn-iconify';

const { Icon } = createIconAliases({
aliases: {
tabHome: 'mdi:home',
tabSearch: 'mdi:magnify',
tabProfile: 'mdi:account',
tabSettings: 'mdi:cog',
} as const,
});

// Use alias names in navigation
<Tab.Screen
name="Home"
options={{
tabBarIcon: createTabBarIcon('mdi:home'), // Direct icon reference
}}
/>

Focused/Unfocused Statesโ€‹

Different icons for focused and unfocused states:

<Tab.Screen
name="Home"
options={{
tabBarIcon: createTabBarIcon({
focused: 'mdi:home',
unfocused: 'mdi:home-outline',
}),
}}
/>

<Tab.Screen
name="Heart"
options={{
tabBarIcon: createTabBarIcon({
focused: 'mdi:heart',
unfocused: 'mdi:heart-outline',
}),
}}
/>

Badge Supportโ€‹

Add badges to tab icons:

<Tab.Screen
name="Notifications"
options={{
tabBarIcon: createTabBarIcon('mdi:bell'),
tabBarBadge: 3, // React Navigation's built-in badge
}}
/>

TypeScript Supportโ€‹

Full type safety with navigation:

import { BottomTabScreenProps } from '@react-navigation/bottom-tabs';
import { createTabBarIcon } from 'rn-iconify';

type RootTabParamList = {
Home: undefined;
Search: { query?: string };
Profile: { userId: string };
};

type HomeScreenProps = BottomTabScreenProps<RootTabParamList, 'Home'>;

function HomeScreen({ navigation }: HomeScreenProps) {
// Fully typed navigation
}

Best Practicesโ€‹

1. Consistent Icon Setโ€‹

Use icons from the same set for visual consistency:

// โœ… Good - consistent
tabBarIcon: createTabBarIcon('mdi:home')
tabBarIcon: createTabBarIcon('mdi:magnify')
tabBarIcon: createTabBarIcon('mdi:account')

// โŒ Avoid - mixed sets
tabBarIcon: createTabBarIcon('mdi:home')
tabBarIcon: createTabBarIcon('heroicons:magnifying-glass')
tabBarIcon: createTabBarIcon('lucide:user')

2. Prefetch Navigation Iconsโ€‹

Preload icons for instant rendering:

import { prefetchIcons } from 'rn-iconify';

async function initNavigation() {
await prefetchIcons([
'mdi:home',
'mdi:magnify',
'mdi:account',
'mdi:cog',
'mdi:bell',
]);
}

3. Use Theme Providerโ€‹

Wrap navigation with theme provider:

<IconThemeProvider theme={{ color: colors.primary }}>
<NavigationContainer>
{/* Navigation inherits theme */}
</NavigationContainer>
</IconThemeProvider>

Convenience Functionsโ€‹

createBackIconโ€‹

Create a preconfigured back button icon:

import { createBackIcon } from 'rn-iconify';

<Stack.Screen
name="Details"
options={({ navigation }) => ({
headerLeft: createBackIcon({
onPress: () => navigation.goBack(),
}),
})}
/>

Uses mdi:arrow-left by default. The icon name is fixed, but size, color, and other options can be customized. Use createHeaderIcon for a different icon:

// Use default back icon
createBackIcon({
onPress: () => navigation.goBack(),
size: 28,
accessibilityLabel: 'Go back',
})

// For custom icon, use createHeaderIcon instead
createHeaderIcon({
icon: 'heroicons:arrow-left',
onPress: () => navigation.goBack(),
size: 28,
accessibilityLabel: 'Go back',
})

createCloseIconโ€‹

Create a preconfigured close button icon:

import { createCloseIcon } from 'rn-iconify';

<Modal.Screen
name="FullscreenModal"
options={({ navigation }) => ({
headerLeft: createCloseIcon({
onPress: () => navigation.goBack(),
}),
})}
/>

Uses mdi:close by default.

createMenuIconโ€‹

Create a preconfigured menu/hamburger button icon:

import { createMenuIcon } from 'rn-iconify';
import { DrawerActions } from '@react-navigation/native';

<Stack.Screen
name="Home"
options={({ navigation }) => ({
headerLeft: createMenuIcon({
onPress: () => navigation.dispatch(DrawerActions.openDrawer()),
}),
})}
/>

Uses mdi:menu by default.


Batch Creationโ€‹

createTabBarIconsโ€‹

Create multiple tab icons at once for cleaner code:

import { createTabBarIcons } from 'rn-iconify';

const tabIcons = createTabBarIcons({
Home: { focused: 'mdi:home', unfocused: 'mdi:home-outline' },
Search: { focused: 'mdi:magnify', unfocused: 'mdi:magnify' },
Profile: { focused: 'mdi:account', unfocused: 'mdi:account-outline' },
Settings: { focused: 'mdi:cog', unfocused: 'mdi:cog-outline' },
});

// Use in navigator
<Tab.Navigator>
<Tab.Screen
name="Home"
options={{ tabBarIcon: tabIcons.Home }}
/>
<Tab.Screen
name="Search"
options={{ tabBarIcon: tabIcons.Search }}
/>
<Tab.Screen
name="Profile"
options={{ tabBarIcon: tabIcons.Profile }}
/>
<Tab.Screen
name="Settings"
options={{ tabBarIcon: tabIcons.Settings }}
/>
</Tab.Navigator>

createDrawerIconsโ€‹

Create multiple drawer icons at once:

import { createDrawerIcons } from 'rn-iconify';

const drawerIcons = createDrawerIcons({
Home: 'mdi:home',
Profile: 'mdi:account',
Settings: 'mdi:cog',
Help: 'mdi:help-circle',
Logout: 'mdi:logout',
});

<Drawer.Navigator>
<Drawer.Screen
name="Home"
options={{ drawerIcon: drawerIcons.Home }}
/>
<Drawer.Screen
name="Profile"
options={{ drawerIcon: drawerIcons.Profile }}
/>
</Drawer.Navigator>

Shorthand Functionsโ€‹

tabIconโ€‹

Shorthand alias for createTabBarIcon:

import { tabIcon } from 'rn-iconify';

// Automatically generates focused and unfocused variants
tabBarIcon: tabIcon('mdi', 'home')
// Generates: focused = 'mdi:home', unfocused = 'mdi:home-outline'

// Custom outline suffix
tabBarIcon: tabIcon('mdi', 'home', '-variant')
// Generates: focused = 'mdi:home', unfocused = 'mdi:home-variant'

API Referenceโ€‹

createTabBarIconโ€‹

function createTabBarIcon(
config: SimpleTabBarIconConfig | TabBarIconConfig
): TabBarIconFunction;

// Simple config options
type SimpleTabBarIconConfig =
| string // Same icon for both states
| [string, string]; // [focused, unfocused]

interface TabBarIconConfig {
focused: string; // Icon for focused state
unfocused?: string; // Icon for unfocused state (defaults to focused)
size?: number; // Custom size override
focusedColor?: string; // Color when focused
unfocusedColor?: string; // Color when unfocused
style?: StyleProp<ViewStyle>;
accessibilityLabel?: string;
}

createTabBarIconsโ€‹

function createTabBarIcons<T extends Record<string, SimpleTabBarIconConfig | TabBarIconConfig>>(
configs: T
): { [K in keyof T]: TabBarIconFunction };

createDrawerIconโ€‹

function createDrawerIcon(
config: string | DrawerIconConfig
): DrawerIconFunction;

interface DrawerIconConfig {
icon: string; // Default icon
focusedIcon?: string; // Icon when focused
size?: number; // Custom size override
style?: StyleProp<ViewStyle>;
}

createDrawerIconsโ€‹

function createDrawerIcons<T extends Record<string, string | DrawerIconConfig>>(
configs: T
): { [K in keyof T]: DrawerIconFunction };

createHeaderIconโ€‹

function createHeaderIcon(config: HeaderIconConfig): (props: HeaderIconProps) => React.ReactNode;

interface HeaderIconConfig {
icon: string; // Icon name (required)
size?: number; // Icon size (default: 24)
color?: string; // Icon color (uses navigation tintColor if not set)
onPress?: () => void; // Press handler
style?: StyleProp<ViewStyle>;
accessibilityLabel?: string;
hitSlop?: { top?: number; bottom?: number; left?: number; right?: number };
}

createBackIconโ€‹

function createBackIcon(
options?: Omit<HeaderIconConfig, 'icon'>
): (props: HeaderIconProps) => React.ReactNode;

Uses mdi:arrow-left with accessibilityLabel: "Go back".

createCloseIconโ€‹

function createCloseIcon(
options?: Omit<HeaderIconConfig, 'icon'>
): (props: HeaderIconProps) => React.ReactNode;

Uses mdi:close with accessibilityLabel: "Close".

createMenuIconโ€‹

function createMenuIcon(
options?: Omit<HeaderIconConfig, 'icon'>
): (props: HeaderIconProps) => React.ReactNode;

Uses mdi:menu with accessibilityLabel: "Open menu".

tabIconโ€‹

function tabIcon(
prefix: string,
name: string,
outlineSuffix?: string // Default: '-outline'
): TabBarIconFunction;

Next Stepsโ€‹