How to create Custom Dark Theme using Context API in React Native

Context API helps to pass data through your react native application without having to pass a prop explicitly. It allows to store and share data globally. Thus, context API can be used as an alternative for state management libraries such as Redux.

In this blog post, let’s see how to create a custom dark mode using context API in a react native application with the help of an example. If you want then you can read more about context API here.

Create a folder named src and then create a file named ThemeContext.js in it. It consists of the newly created ThemeContext. By default dark theme is not enabled. The ThemeProvider consists of darkTheme which is false by default and the toggle function which toggles the dark mode. See the code of ThemeContext.js given below.

import React from 'react';

export const ThemeContext = React.createContext();

export const ThemeProvider = ({children}) => {
  const [darkTheme, setDarkTheme] = React.useState(false);
  const toggle = () => {
    setDarkTheme(!darkTheme);
  };
  return (
    <ThemeContext.Provider value={{darkTheme, toggle}}>
      {children}
    </ThemeContext.Provider>
  );
};

There are two screens in this react native example. One Screen is ChangeTheme.js and the other one is Home.js. The button to toggle the dark theme will be in ChangeTheme.js You can navigate to Home from the ChangeTheme screen. I have done navigation with react navigation library and if you want to add it then follow all instructions given here.

The App.js file will look as given below.

import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import {ThemeProvider} from './src/ThemeContext';
import ChangeTheme from './src/ChangeTheme';
import Home from './src/Home';

const Stack = createNativeStackNavigator();

const App = () => {
  return (
    <ThemeProvider>
      <NavigationContainer>
        <Stack.Navigator>
          <Stack.Screen name="ChangeTheme" component={ChangeTheme} />
          <Stack.Screen name="Home" component={Home} />
        </Stack.Navigator>
      </NavigationContainer>
    </ThemeProvider>
  );
};

export default App;

As you can see, the ThemeProvider is wrapped around NavigationContainer to make context API applicable to all screens of the app.

Create a separate file named Themes.js to keep the color data for separate themes.

const Themes = {
  light: {
    foreground: '#000000',
    background: '#dddddd',
  },
  dark: {
    foreground: '#ffffff',
    background: '#222222',
  },
};

export default Themes;

Coming to ChangeTheme.js, it has two Pressable components, one changes the theme, and the other navigate to the Home screen. The useContext hook is used here to fetch data. The toggle function helps to enable and disable the dark mode.

import {StyleSheet, Text, Pressable, View} from 'react-native';
import React from 'react';
import {ThemeContext} from './ThemeContext';
import Themes from './Themes';

const ChangeTheme = ({navigation}) => {
  const {darkTheme, toggle} = React.useContext(ThemeContext);
  return (
    <View style={styles.container}>
      <Pressable
        onPress={toggle}
        style={[
          styles.button,
          {
            backgroundColor: darkTheme
              ? Themes.dark.background
              : Themes.light.background,
          },
        ]}>
        <Text
          style={{
            color: darkTheme ? Themes.dark.foreground : Themes.light.foreground,
          }}>
          Change Theme
        </Text>
      </Pressable>
      <Pressable onPress={() => navigation.navigate('Home')}>
        <Text style={{color: 'blue'}}>Navigate to Home</Text>
      </Pressable>
    </View>
  );
};

export default ChangeTheme;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  button: {
    padding: 10,
    margin: 10,
    width: '80%',
    alignItems: 'center',
  },
});

On pressing the Change Theme button the background color is changed.

Following is the code of Home.js where the background color is changed according to the selected theme.

import {StyleSheet, Text, View} from 'react-native';
import React from 'react';
import {ThemeContext} from './ThemeContext';
import Themes from './Themes';
const Home = () => {
  const {darkTheme} = React.useContext(ThemeContext);
  return (
    <View
      style={[
        styles.container,
        {
          backgroundColor: darkTheme
            ? Themes.dark.background
            : Themes.light.background,
        },
      ]}>
      <Text
        style={{
          color: darkTheme ? Themes.dark.foreground : Themes.light.foreground,
        }}>
        This is Home!
      </Text>
    </View>
  );
};

export default Home;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

Following is the output of this react native custom theme with context API example.

Also read, how to detect dark mode enabled in react native.

That’s how you can use context API in react native. The whole code is available as a GitHub repository here.

Similar Posts