Skip to main content
useColorScheme is a React hook that allows you to detect and respond to the user’s system color scheme preference. It automatically updates when the user changes their device’s appearance settings.

Signature

function useColorScheme(): 'light' | 'dark' | null | undefined

Returns

  • 'light' - The user has light mode enabled
  • 'dark' - The user has dark mode enabled
  • null or undefined - The color scheme could not be determined

Usage

import { useColorScheme, View, Text, StyleSheet } from 'react-native';

function ThemedComponent() {
  const colorScheme = useColorScheme();

  return (
    <View
      style={[
        styles.container,
        colorScheme === 'dark' ? styles.darkContainer : styles.lightContainer,
      ]}
    >
      <Text style={colorScheme === 'dark' ? styles.darkText : styles.lightText}>
        Current theme: {colorScheme}
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  lightContainer: {
    backgroundColor: '#ffffff',
  },
  darkContainer: {
    backgroundColor: '#000000',
  },
  lightText: {
    color: '#000000',
  },
  darkText: {
    color: '#ffffff',
  },
});

Common Patterns

Dynamic Styling

function DynamicThemedComponent() {
  const colorScheme = useColorScheme();

  const backgroundColor = colorScheme === 'dark' ? '#1a1a1a' : '#f5f5f5';
  const textColor = colorScheme === 'dark' ? '#ffffff' : '#000000';

  return (
    <View style={{ backgroundColor, padding: 20 }}>
      <Text style={{ color: textColor }}>Themed content</Text>
    </View>
  );
}

Theme Context Provider

import { useColorScheme } from 'react-native';
import { createContext, useContext, ReactNode } from 'react';

type Theme = {
  dark: boolean;
  colors: {
    background: string;
    text: string;
    primary: string;
  };
};

const ThemeContext = createContext<Theme | undefined>(undefined);

export function ThemeProvider({ children }: { children: ReactNode }) {
  const colorScheme = useColorScheme();

  const theme: Theme = {
    dark: colorScheme === 'dark',
    colors: {
      background: colorScheme === 'dark' ? '#000000' : '#ffffff',
      text: colorScheme === 'dark' ? '#ffffff' : '#000000',
      primary: colorScheme === 'dark' ? '#bb86fc' : '#6200ee',
    },
  };

  return (
    <ThemeContext.Provider value={theme}>
      {children}
    </ThemeContext.Provider>
  );
}

export function useTheme() {
  const theme = useContext(ThemeContext);
  if (!theme) {
    throw new Error('useTheme must be used within ThemeProvider');
  }
  return theme;
}

Null Safety Handling

function SafeThemedComponent() {
  const colorScheme = useColorScheme();

  // Fallback to 'light' if colorScheme is null/undefined
  const isDark = colorScheme === 'dark';

  return (
    <View style={{ backgroundColor: isDark ? '#000' : '#fff' }}>
      <Text style={{ color: isDark ? '#fff' : '#000' }}>
        Theme active
      </Text>
    </View>
  );
}

Implementation Details

This hook uses React’s useSyncExternalStore to subscribe to system appearance changes. It automatically:
  • Subscribes to appearance changes when the component mounts
  • Updates the component when the system color scheme changes
  • Cleans up the subscription when the component unmounts

Platform Support

  • iOS: Supported on iOS 13 and above
  • Android: Supported on Android 10 (API level 29) and above
  • Web: Respects prefers-color-scheme media query
On older platforms, the hook may return null or undefined.

See Also

Build docs developers (and LLMs) love