TL;DR
If you prefer to dive straight into some code or follow along using project files, head over to the Github repo for this article and clone it to test and make your own changes!
This repo is meant to hold the code files for the Medium article Hail to the Theme.
About
This is a demo application that utilizes the Expo framework to create a React Native-based mobile app capable of switching between custom light and dark color palettes depending on the host device settings.
The application makes use primarily of customized components offered by the awesome React Native Paper and React Navigation frameworks
You can create your own custom Material UI color palettes by going to react-native-paper's theme generator page.
Live Development
To run in live development mode, run npx expo start in the project root directory. This will start an interactive command line utility allowing you choose which device to run your app on:
Test on a physical device using the Expo Go mobile app (scan the QR for easy setup)
Love them or hate theme, themes are all around us! Our operating systems provide custom theme options (some more than others), many popular web browsers allow for installing custom theme extensions…and of course, so do our mobile phones!
While mobile device theming may be a bit more limited than the other avenues mentioned above, there’s still the underlying commonality between both iOS and Android of now providing Light and Dark themes for core applications.
Before we dive into coding our app, it’s important to explain the means in which we do it! The example application used for this article will be written almost exclusively in JavaScript…more specifically Extended JavaScript (or JSX). This may come as a shock to those new to cross-platform development, who typically think of Java and Swift as being the only way to build a mobile app. It’s true, both Java/Kotlin as well as Swift/Objective-C are primary languages used to build mobile applications for Android and iOS respectively…but they aren’t the only way!
Enter React Native
React Native combines the best parts of native development with React, a best-in-class JavaScript library for building user interfaces…
…Create platform-specific versions of components so a single codebase can share code across platforms. With React Native, one team can maintain two platforms and share a common technology — React.
By using React Native, we’ll be able to take advantage of the power and flexibility offered by React, and also have the ability to re-use custom components to build mobile apps that can be run on both Android and iOS…all with the same code base!
To get our project set up, we’ll be using the outstanding Expo framework and its CLI (command line interface). Expo has become one of the most widely used tools for mobile development with react native, not just because of how simple it makes getting a project started, but also for the wealth of libraries it offers to customize the look and functionality of your app!
It’s important to make sure we have the following system requirements installed:
Node.js LTS Release (using the LTS specific release is important)
Git
Watchman (for Linux/macOS systems)
Yarn (not required, but recommended by Expo)
Open up your favorite terminal application or PowerShell, and navigate to where you plan to create your project directory. Once there, run the following to create a new expo project:
npx create-expo-app example-app &&cd example-app
The Code
Alright, let’s get to the good stuff! Now that we have our basic setup, we’ll go ahead and create some components to put together in a small example app to look at how theming can be utilized in a straightforward way. The application will represent a store shopping list app, which adjusts its component theming based on whether the user’s device is set to light or dark mode.
The first and arguably most important step for us is to create a set of colors to use for our app’s theme. This project utilizes an awesome React Native framework react-native-paper. It will provide the key components used for building our UI. A great feature that can be found on their website is a generator for Material UI themes based on a provided primary color:
This fantastic tool not only takes the hard work out of creating proper light and dark color palette objects, but also follows the Material Design guidelines that all new versions of Android follow…allowing our app to effectively feel and look like any other natively built application!
If you haven’t done so already, make sure to add the following dependencies to your package.json to get all the magic installed:
To use the theme objects we previously created, go ahead and open your project's App.js file and add them, as well as the other import statements for expo and react-native-paper :
The above gist is where all the theming magic happens in our app! We declare our theme objects using the color palette values generated by react-native-paper. Expo provides an API for adjusting the top status bar color depending on whether the device is set to dark or light mode, so we make sure to include that as well. The other important piece of this code involves the use of the useColorScheme hook when defining our two theme providers. This will allow our themes to be passed down and accessed by all child components in the app.
Speaking of Components
You may have noticed a particular import statement in the code above adding a MainNavigator component. This is where the primary navigation functionality of our app resides, and makes use of another powerful and appropriately named react-navigation framework to do so. Before we take a look at our Navigator, let’s throw together a couple smaller components to incorporate in our UI:
With our component files defined, we can now go ahead and import them into our MainNavigator file, along with the navigation components provided by react-navigation :
If you paid close attention, you may have noticed the key line(s) of code that allow us to apply our custom theme colors to the app’s components.
import { ..., useTheme, ... } from 'react-native-paper';
It’s this useTheme hook that allows us to access the custom theme objects passed down from the very top of our application. All that’s required to use these colors is calling the hook and storing the return value inside a variable, like in our PrimaryScreen component:
Testing
To run our new project in live development mode, run npx expo start in the project root directory. This will start an interactive command line utility allowing you choose which device to test your app on:
Test on a physical device using the Expo Go mobile app (scan the QR for easy setup)
Run on an Android emulator (using Android Studio)
Run on iOS emulator device (using Xcode)
The process of implementing custom themes can seem rather daunting at first for many developers, including myself. With the help of some amazing frameworks, however, it can be accomplished (relatively) painlessly!