Skip to content

Theme Hooks

The useTheme hook is the primary interface for accessing and managing theme functionality in your React Native application.

MyComponent.tsx
import { useTheme } from 'your-theme-package';
function MyComponent() {
const { theme, isDark, setThemeMode } = useTheme();
return (
<View style={{ backgroundColor: theme.colors.background }}>
<Text style={{ color: theme.colors.text }}>
Current mode: {isDark ? 'dark' : 'light'}
</Text>
</View>
);
}

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.

setThemeMode(mode: ThemeMode): void Method

Section titled “setThemeMode(mode: ThemeMode): void ”

Changes the theme mode and persists the selection to storage.

Theme Mode Switching
const { setThemeMode } = useTheme();
// Switch to dark mode
setThemeMode('dark');
// Follow system preference
setThemeMode('light');

updateCustomTheme(customTheme, preset?, presetConfig?): void Method

Section titled “updateCustomTheme(customTheme, preset?, presetConfig?): void ”

Updates the current theme with custom styling.

const { updateCustomTheme } = useTheme();
// Apply custom colors
updateCustomTheme({
colors: {
primary: '#007AFF',
secondary: '#FF9500'
}
});

Resets theme to default state, removing all customizations and presets.

Reset Theme
const { resetTheme } = useTheme();
// Reset to default theme
resetTheme();
ThemedButton.tsx
function ThemedButton({ children, onPress }) {
const { theme, isDark } = useTheme();
const buttonStyle = {
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,
};
return (
<TouchableOpacity style={buttonStyle} onPress={onPress}>
<Text style={{ color: theme.colors.onPrimary }}>
{children}
</Text>
</TouchableOpacity>
);
}
ThemeCustomizer.tsx
function ThemeCustomizer() {
const { theme, updateCustomTheme, activePreset } = useTheme();
const applyBrandTheme = () => {
updateCustomTheme(
{
colors: {
primary: '#FF6B6B',
secondary: '#4ECDC4',
accent: '#45B7D1',
}
},
'brand-theme'
);
};
return (
<View>
<Text>Active Preset: {activePreset || 'Default'}</Text>
<Button title="Apply Brand Theme" onPress={applyBrandTheme} />
</View>
);
}
AdaptiveComponent.tsx
function AdaptiveComponent() {
const { isDark, themeMode, setThemeMode } = useTheme();
useEffect(() => {
// Automatically adjust based on time of day
const hour = new Date().getHours();
if (themeMode === 'system') {
// System will handle this automatically
return;
}
// Custom logic for auto-switching
if (hour >= 18 || hour <= 6) {
setThemeMode('dark');
} else {
setThemeMode('light');
}
}, []);
return (
<View>
<Text>Theme adapts to: {themeMode}</Text>
<Text>Currently {isDark ? 'dark' : 'light'} mode</Text>
</View>
);
}

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
return <View />;
}

The hook is fully typed and provides excellent IntelliSense support:

TypedComponent.tsx
import { useTheme } from 'your-theme-package';
import type { Theme, ThemeMode } from 'your-theme-package/types';
function TypedComponent() {
const {
theme, // Type: Theme
themeMode, // Type: ThemeMode
isDark, // Type: boolean
setThemeMode, // Type: (mode: ThemeMode) => void
} = useTheme();
// 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 }} />;
}
ExpensiveThemedComponent.tsx
function ExpensiveThemedComponent() {
const { theme, isDark } = useTheme();
const complexStyles = useMemo(() => {
// Expensive style calculations
return generateComplexStyles(theme, isDark);
}, [theme, isDark]);
return <View style={complexStyles} />;
}
  1. Always use within RNCProvider: Ensure useTheme is called within components wrapped by RNCProvider

  2. Destructure selectively: Only extract the values you need to minimize re-renders

  3. Leverage TypeScript: Use the provided types for better development experience

  4. Test theme switching: Always test your components in both light and dark modes

  5. Handle edge cases: Consider how your UI looks during theme transitions

  6. 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.