The useTheme
hook is the primary interface for accessing and managing theme functionality in your React Native application.
import { useTheme } from 'your-theme-package';
const { theme, isDark, setThemeMode } = useTheme();
<View style={{ backgroundColor: theme.colors.background }}>
<Text style={{ color: theme.colors.text }}>
Current mode: {isDark ? 'dark' : 'light'}
The useTheme
hook returns an object with the following properties:
theme: Theme
The current active theme object containing:
colors
- Color palette for the current theme
fontSizes
- Typography scale definitions
spacing
- Spacing scale for consistent layouts
components
- Component-specific styling tokens
typography
- Font family and weight definitions
themeMode: ThemeMode
Current theme mode setting. Can be:
'light'
- Force light theme
'dark'
- Force dark theme
'system'
- Follow system preference
isDark: boolean
Boolean indicating if dark theme is currently active. Automatically resolves based on:
- Explicit mode selection (
'light'
or 'dark'
)
- System preference when mode is
'system'
activePreset?: string
Name of the currently active theme preset, if any.
Changes the theme mode and persists the selection to storage.
const { setThemeMode } = useTheme();
// Follow system preference
Updates the current theme with custom styling.
const { updateCustomTheme } = useTheme();
// Apply preset with dynamic generation
{ colors: { primary: '#007AFF' } },
primary: isDark ? '#0A84FF' : '#007AFF',
background: isDark ? '#000000' : '#FFFFFF'
Resets theme to default state, removing all customizations and presets.
const { resetTheme } = useTheme();
// Reset to default theme
function ThemedButton({ children, onPress }) {
const { theme, isDark } = useTheme();
backgroundColor: theme.colors.primary,
padding: theme.spacing.md,
borderRadius: theme.components.borderRadius.md,
// Add dark mode specific styling
shadowColor: isDark ? theme.colors.text : theme.colors.shadow,
<TouchableOpacity style={buttonStyle} onPress={onPress}>
<Text style={{ color: theme.colors.onPrimary }}>
function ThemeCustomizer() {
const { theme, updateCustomTheme, activePreset } = useTheme();
const applyBrandTheme = () => {
<Text>Active Preset: {activePreset || 'Default'}</Text>
<Button title="Apply Brand Theme" onPress={applyBrandTheme} />
function AdaptiveComponent() {
const { isDark, themeMode, setThemeMode } = useTheme();
// Automatically adjust based on time of day
const hour = new Date().getHours();
if (themeMode === 'system') {
// System will handle this automatically
// Custom logic for auto-switching
if (hour >= 18 || hour <= 6) {
<Text>Theme adapts to: {themeMode}</Text>
<Text>Currently {isDark ? 'dark' : 'light'} mode</Text>
The useTheme
hook includes built-in error handling:
// ❌ This will throw an error
function ComponentOutsideProvider() {
const theme = useTheme(); // Error: useTheme must be used within a ThemeProvider
// ✅ Correct usage within provider
The hook is fully typed and provides excellent IntelliSense support:
import { useTheme } from 'your-theme-package';
import type { Theme, ThemeMode } from 'your-theme-package/types';
function TypedComponent() {
themeMode, // Type: ThemeMode
setThemeMode, // Type: (mode: ThemeMode) => void
// Full type safety and autocompletion
const primaryColor = theme.colors.primary; // ✅ Typed
// const invalid = theme.colors.invalid; // ❌ TypeScript error
Only destructure the values you need to optimize re-renders:
// ✅ Good - only subscribes to theme changes
function OptimizedComponent() {
const { theme } = useTheme();
return <View style={{ backgroundColor: theme.colors.background }} />;
// ⚠️ Less optimal - subscribes to all theme context changes
function ComponentWithAllValues() {
const themeContext = useTheme();
return <View style={{ backgroundColor: themeContext.theme.colors.background }} />;
function ExpensiveThemedComponent() {
const { theme, isDark } = useTheme();
const complexStyles = useMemo(() => {
// Expensive style calculations
return generateComplexStyles(theme, isDark);
return <View style={complexStyles} />;
-
Always use within RNCProvider: Ensure useTheme
is called within components wrapped by RNCProvider
-
Destructure selectively: Only extract the values you need to minimize re-renders
-
Leverage TypeScript: Use the provided types for better development experience
-
Test theme switching: Always test your components in both light and dark modes
-
Handle edge cases: Consider how your UI looks during theme transitions
-
Use semantic colors: Prefer semantic color names (primary
, background
) over specific values (blue
, white
)
Hook called outside provider
Error:
Error: useTheme must be used within a ThemeProvider
Solution: Wrap your app with RNCProvider
Theme not persisting
Check that AsyncStorage permissions are properly configured in your React Native app.
Custom theme not applied
Ensure you’re calling updateCustomTheme
with valid theme properties that match the Theme interface.