Skip to main content

Theme Provider

Configure global defaults for all icons in your app using the IconThemeProvider.

Basic Usageโ€‹

Wrap your app with IconThemeProvider to set global defaults:

import { IconThemeProvider, Mdi, Heroicons } from 'rn-iconify';

function App() {
return (
<IconThemeProvider
theme={{
size: 24,
color: '#333333',
}}
>
{/* All icons inherit these defaults */}
<Mdi name="home" /> {/* size=24, color=#333333 */}
<Heroicons name="user" /> {/* size=24, color=#333333 */}
</IconThemeProvider>
);
}

Theme Optionsโ€‹

OptionTypeDefaultDescription
sizenumber24Default icon size
colorstring'#000000'Default icon color
placeholderReactNode | 'shimmer' | 'pulse' | 'skeleton'-Default placeholder while loading
placeholderColorstring'#E1E1E1'Placeholder background color
placeholderDurationnumber1000Placeholder animation duration (ms)
rotatenumber0Default rotation for all icons (any degree value)
flip'horizontal' | 'vertical' | 'both'-Default flip direction
fallbackDelaynumber0Delay before showing fallback (ms)

Full Exampleโ€‹

import { IconThemeProvider, Mdi } from 'rn-iconify';
import { ActivityIndicator } from 'react-native';

function App() {
return (
<IconThemeProvider
theme={{
size: 20,
color: '#6366f1',
placeholder: <ActivityIndicator size="small" color="#6366f1" />,
}}
>
<Navigation />
</IconThemeProvider>
);
}
v3.0 Improvement

The theme provider was rewritten in v3.0 to use useMemo instead of useState + useEffect. Inline theme objects like theme={{ size: 20 }} no longer cause infinite re-render loops. You can safely remove any useMemo workarounds you may have added.

Override Theme Valuesโ€‹

Individual icons can override theme defaults:

import { IconThemeProvider, Mdi } from 'rn-iconify';

function App() {
return (
<IconThemeProvider theme={{ size: 24, color: 'blue' }}>
<Mdi name="home" /> {/* size=24, color=blue */}
<Mdi name="settings" size={32} /> {/* size=32, color=blue */}
<Mdi name="heart" color="red" /> {/* size=24, color=red */}
<Mdi name="star" size={48} color="gold" /> {/* size=48, color=gold */}
</IconThemeProvider>
);
}

Dark Mode Supportโ€‹

Integrate with your app's theme system:

import { IconThemeProvider, Mdi } from 'rn-iconify';
import { useColorScheme } from 'react-native';

function App() {
const colorScheme = useColorScheme();
const isDark = colorScheme === 'dark';

return (
<IconThemeProvider
theme={{
size: 24,
color: isDark ? '#ffffff' : '#000000',
}}
>
<MainApp />
</IconThemeProvider>
);
}

With React Navigationโ€‹

Combine with React Navigation's theme:

import { IconThemeProvider } from 'rn-iconify';
import { NavigationContainer, useTheme } from '@react-navigation/native';

function ThemedApp() {
const { colors } = useTheme();

return (
<IconThemeProvider
theme={{
size: 24,
color: colors.text,
}}
>
<AppNavigator />
</IconThemeProvider>
);
}

function App() {
return (
<NavigationContainer>
<ThemedApp />
</NavigationContainer>
);
}

Nested Providersโ€‹

Theme providers can be nested for section-specific styling:

import { IconThemeProvider, Mdi } from 'rn-iconify';

function App() {
return (
<IconThemeProvider theme={{ color: 'gray' }}>
{/* Gray icons */}
<Mdi name="home" />

<IconThemeProvider theme={{ color: 'blue' }}>
{/* Blue icons in this section */}
<Mdi name="settings" />
<Mdi name="user" />
</IconThemeProvider>

{/* Back to gray */}
<Mdi name="menu" />
</IconThemeProvider>
);
}

useIconTheme Hookโ€‹

Access and modify theme values programmatically:

import { useIconTheme, Mdi } from 'rn-iconify';
import { View, Text, Button } from 'react-native';

function IconWithLabel({ name, label }: { name: string; label: string }) {
const { theme } = useIconTheme();

return (
<View style={{ alignItems: 'center' }}>
<Mdi name={name} />
<Text style={{ color: theme.color, fontSize: theme.size ? theme.size / 2 : 12 }}>
{label}
</Text>
</View>
);
}

// Dynamic theme updates
function ThemeToggle() {
const { theme, setTheme } = useIconTheme();

const toggleDarkMode = () => {
setTheme(prev => ({
...prev,
color: prev.color === '#000000' ? '#ffffff' : '#000000',
}));
};

return <Button title="Toggle Theme" onPress={toggleDarkMode} />;
}

TypeScriptโ€‹

Full TypeScript support:

import { IconThemeProvider, IconTheme } from 'rn-iconify';

const myTheme: IconTheme = {
size: 24,
color: '#333',
placeholder: 'shimmer',
};

function App() {
return (
<IconThemeProvider theme={myTheme}>
<MainApp />
</IconThemeProvider>
);
}

Best Practicesโ€‹

1. Single Root Providerโ€‹

Place one provider at your app root:

// โœ… Good
function App() {
return (
<IconThemeProvider theme={{ size: 24 }}>
<MainApp />
</IconThemeProvider>
);
}

// โŒ Avoid - multiple root providers
function App() {
return (
<>
<IconThemeProvider theme={{ size: 24 }}>
<Header />
</IconThemeProvider>
<IconThemeProvider theme={{ size: 24 }}>
<Content />
</IconThemeProvider>
</>
);
}

2. Semantic Color Namesโ€‹

Use your app's color tokens:

import { colors } from './theme';

<IconThemeProvider theme={{ color: colors.primary }}>

3. Responsive Sizingโ€‹

Adjust based on screen size:

import { useWindowDimensions } from 'react-native';

function App() {
const { width } = useWindowDimensions();
const iconSize = width > 768 ? 28 : 24;

return (
<IconThemeProvider theme={{ size: iconSize }}>
<MainApp />
</IconThemeProvider>
);
}

Advanced Hooksโ€‹

useIconThemeValueโ€‹

Get a specific theme value:

import { useIconThemeValue } from 'rn-iconify';

function ColorIndicator() {
const color = useIconThemeValue('color');
const size = useIconThemeValue('size');

return (
<View>
<Text>Current color: {color}</Text>
<Text>Current size: {size}</Text>
</View>
);
}

useMergedIconPropsโ€‹

Merge component props with theme defaults:

import { useMergedIconProps } from 'rn-iconify';

function CustomIcon({ name, size, color, ...rest }) {
const mergedProps = useMergedIconProps({ name, size, color, ...rest });

// mergedProps has theme defaults filled in for any missing values
return <SvgIcon {...mergedProps} />;
}

Example merge behavior:

// Theme: { size: 24, color: '#333' }
// Props: { size: 32 }
// Result: { size: 32, color: '#333' }

IconThemeContextโ€‹

Access the raw React context for advanced use cases:

import { useContext } from 'react';
import { IconThemeContext } from 'rn-iconify';

function ThemeDebugger() {
const context = useContext(IconThemeContext);

if (!context) {
return <Text>No theme provider found</Text>;
}

return (
<View>
<Text>Theme: {JSON.stringify(context.theme)}</Text>
<Button
title="Reset"
onPress={() => context.setTheme({ size: 24, color: '#000' })}
/>
</View>
);
}

Context Valueโ€‹

interface IconThemeContextValue {
/** Current theme values */
theme: IconTheme;

/** Update theme (accepts partial or function) */
setTheme: (theme: IconTheme | ((prev: IconTheme) => IconTheme)) => void;
}

Utility Functionsโ€‹

mergeWithDefaultsโ€‹

Merge theme values with defaults. Ensures all required properties have values:

import { mergeWithDefaults } from 'rn-iconify';

const customTheme = { size: 32 };

// Merges with DEFAULT_ICON_THEME
const merged = mergeWithDefaults(customTheme);
// { size: 32, color: '#000000', placeholderColor: '#E1E1E1', ... }

This is useful when creating custom theme providers or ensuring theme completeness.

useMergedIconPropsโ€‹

Hook version for use inside components:

import { useMergedIconProps, Mdi } from 'rn-iconify';

function CustomIcon({ size, color, name }) {
// Merges provided props with theme defaults
const mergedProps = useMergedIconProps({ size, color });

return <Mdi name={name} {...mergedProps} />;
}

// Usage
<CustomIcon name="home" /> // Uses theme size/color
<CustomIcon name="settings" size={24} /> // size=24, theme color

Theme Persistenceโ€‹

Save and restore theme across app restarts:

import { IconThemeProvider } from 'rn-iconify';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useState, useEffect } from 'react';

function App() {
const [theme, setTheme] = useState({ size: 24, color: '#333' });
const [loaded, setLoaded] = useState(false);

// Load saved theme
useEffect(() => {
AsyncStorage.getItem('iconTheme').then(saved => {
if (saved) {
setTheme(JSON.parse(saved));
}
setLoaded(true);
});
}, []);

// Save theme changes
const handleThemeChange = (newTheme) => {
setTheme(newTheme);
AsyncStorage.setItem('iconTheme', JSON.stringify(newTheme));
};

if (!loaded) return null;

return (
<IconThemeProvider theme={theme}>
<MainApp onThemeChange={handleThemeChange} />
</IconThemeProvider>
);
}

Theme Presetsโ€‹

Create reusable theme presets:

import { IconTheme } from 'rn-iconify';

export const themes = {
light: {
size: 24,
color: '#1a1a1a',
placeholderColor: '#e5e5e5',
} as IconTheme,

dark: {
size: 24,
color: '#ffffff',
placeholderColor: '#333333',
} as IconTheme,

compact: {
size: 18,
color: '#666666',
} as IconTheme,

large: {
size: 32,
color: '#1a1a1a',
} as IconTheme,
};

// Usage
<IconThemeProvider theme={themes.dark}>
<MainApp />
</IconThemeProvider>

Theme Compositionโ€‹

Combine multiple theme sources:

import { IconThemeProvider } from 'rn-iconify';

function App() {
const systemTheme = useSystemTheme(); // from OS
const userTheme = useUserPreferences(); // from settings
const brandTheme = { color: '#6366f1' }; // brand colors

// Merge themes with priority: user > brand > system
const combinedTheme = {
...systemTheme,
...brandTheme,
...userTheme,
};

return (
<IconThemeProvider theme={combinedTheme}>
<MainApp />
</IconThemeProvider>
);
}

Next Stepsโ€‹