Update Your React Native App Using Remote Config

A step-by-step tutorial for updating your application using Remote Config. With feature flags, we can turn a feature on or off without the need to deploy. In addition to that, with a remote config, we can add and remove things within a feature that helps us exploit the true power of feature flags with Flagsmith. Mobile apps are one of the best candidates for a remote config as we have less control over when they are deployed.

Advantages of Remote config

Remote config is the icing on the feature flag cake, below are some notable advantages of remote config:

  1. Dynamically change how a feature behaves on the fly even for static clients like mobile applications.
  2. Similar to feature flags they can be turned on and off as per the need.

Example: Control the theme options with Remote config

For this step-by-step walkthrough, we will take a demo React Native/Expo app and add a remote config to control the theme options we want to show on the home screen. A mobile app serves as one of the best candidates for a remote config as we have less control over when it is deployed.

Prerequisites

Before we jump into the code, here are some prerequisites for us to be aware of:

  1. Have Node.js and yarn running on your system.
  2. You know how to use git and GitHub in general.
  3. You know that mobile apps are static clients, meaning the application publishers don’t have control over when the user will update their local application to a newer version.
  4. You have a working Flagsmith account and have created a feature flag and played around a bit with it. If you have not done that please read this deployment is not a release step by step example post.

Making the demo app work

We will be using an expo multi-screen started demo app which is open source. To get this app working locally as a web application we can do the following:

  1. Clone the repository with `git clone git@github.com:calebnance/expo-multi-screen-starter.git`
  2. Then go into the folder with `cd export-multi-screen-starter`
  3. After that run `yarn install`, it will download all the needed dependency; might take a couple of minutes depending on your internet connection, below is how it ran for me:
Metro Bundler Application — starting screen
Metro Bundler Application — starting screen
Home screen of application with “light theme” and “dark theme” options
Home screen of application with “light theme” and “dark theme” options

Creating the remote config on Flagsmith

The goal here is to dynamically control the themes displayed on the main screen without the need to change any code or resubmit your application to any of the app stores. For this post, we assume you have already registered on Flagsmith and have played around to create your first feature flag on a project. Now, let’s proceed to create our first remote config.

Screenshot of creating the themes remote config feature in the Flagsmith application
Screenshot of creating the themes remote config feature in the Flagsmith application

Add Flagsmith to the React Native app

As we have the remote config set up on our Flagsmith project and relevant environments, we will add two NPM packages react native flagsmith and react native async storage to the project with the following command:

```bash
yarn add react-native-flagsmith @react-native-community/async-storage
```

Enable remote config in our demo app

To add the remote config to our demo react native expo we will change the `App.js` file on the root of the project to look like below:

```js
import * as React from 'react';
import { StatusBar } from 'react-native';
import { ScreenOrientation } from 'expo';
import AppLoading from 'expo-app-loading';
import { Appearance } from 'react-native-appearance';
import { device, func } from './src/constants';
import flagsmith from 'react-native-flagsmith';
// tab navigator
import Stack from './src/navigation/Stack';
import AsyncStorage from '@react-native-community/async-storage';
const environmentID = "nzSwVvSBKPXat8gM6guipa";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
theme: 'light'
};
// is iPad?
if (device.isPad) {
ScreenOrientation.allowAsync(
ScreenOrientation.Orientation.ALL_BUT_UPSIDE_DOWN
);
}
this.updateTheme = this.updateTheme.bind(this);
}
componentDidMount() {
const { handleFlags, handleFlagsError } = this;
flagsmith.init({
environmentID,
cacheFlags: true,
AsyncStorage,
enableLogs: false,
onChange: handleFlags,
onError: handleFlagsError
});
flagsmith.startListening(12000);
// get system preference
const colorScheme = Appearance.getColorScheme();
// if light or dark
if (colorScheme !== 'no-preference') {
this.setState({
theme: colorScheme
});
}
}
updateTheme(themeType) {
this.setState({
theme: themeType
});
}
render() {
const { isLoading, theme } = this.state;
const iOSStatusType = theme === 'light' ? 'dark-content' : 'light-content';
let themes = ['light'];
if (flagsmith.hasFeature('themes')) {
themes = JSON.parse(flagsmith.getValue('themes'));
}
if (isLoading) {
return (
<AppLoading
onError={console.warn}
onFinish={() => this.setState({ isLoading: false })}
startAsync={func.loadAssetsAsync}
/>
);
}
return (
<React.Fragment>
<StatusBar barStyle={device.iOS ? iOSStatusType : 'light-content'} />
<Stack
screenProps={{
updateTheme: this.updateTheme,
themes
}}
theme={theme}
/>
</React.Fragment>
);
}
handleFlags = (oldFlags, params) => {
this.setState({
...params,
isLoading: false,
logs: [{
timestamp: new Date().toTimeString(),
params: JSON.stringify(params),
oldData: JSON.stringify(oldFlags),
data: JSON.stringify(flagsmith.getAllFlags()),
}].concat(this.state.logs)
});
};
handleFlagsError = (data) => {
console.log('Error getting feature flags', data);
};
}
export default App;
```
  1. On line no. 13, we added the environment ID, we can conveniently find it in the Features page on Flagsmith in the “Code Example” section.
  2. From line no. 35 to 45, we have initialized the Flagsmith client inside `componentDidMount`, We have enabled the cache and disable the logs. Then attached `onChange` and `onError` handlers.
  3. The `startListening` part of Flagsmith polls the API for any changes and passed the value in milliseconds so it will poll the API every 12 seconds for any change. You can read more about this in our docs too.
  4. At line 66, we initialize the `themes` array with `light`, just in case if the Flagsmith API can’t be reached we will still have one theme. Next, we check if the themes remote config is enabled, if it is we will parse the JSON value into the themes variable. In our case, it will be an array with two elements, light and dark.
  5. On line 88, we pass the themes array to the Stack component’s screenProps.
  6. Finally, on lines 95–100 we define the change and error handler. The error handler at the bottom is very basic which just logs the error on the console. The onChange handler does the main part of setting the state with the right parameters.
```js
import * as React from 'react';
import PropTypes from 'prop-types';
import { ScrollView, Text, View } from 'react-native';
import { useTheme } from 'react-navigation';
import { gStyle } from '../constants';
// components
import Touch from '../components/Touch';
const HomeScreen = ({ navigation, screenProps }) => { const theme = useTheme();
return (
<View style={gStyle.container[theme]}>
<ScrollView contentContainerStyle={gStyle.contentContainer}>
<Text style={gStyle.text[theme]}>Home content area</Text>
<View style={gStyle.spacer64} /> <Touch
onPress={() => navigation.navigate('MultiBase')}
text="Jump to Multi tab"
/>
{Array.isArray(screenProps.themes) && screenProps.themes.map(theme => <Touch key={theme} onPress={() => screenProps.updateTheme(theme)} text={theme + ' theme'} />)}
</ScrollView>
</View>
);
};
HomeScreen.navigationOptions = {
headerTitleStyle: gStyle.headerTitleStyle,
title: 'Home'
};
HomeScreen.propTypes = {
// required
navigation: PropTypes.object.isRequired,
screenProps: PropTypes.object.isRequired
};
export default HomeScreen;
```

Test the remote config

As we have added the remote config, installed necessary NPM packages, and updated the code let’s see the remote config in action. To see it running we will run `yarn start` again after we have done the changes on your project to see something like:

Starting the Metro Bundler Application
Starting the Metro Bundler Application
Home screen of application with “light theme” and “dark theme” options
Home screen of application with “light theme” and “dark theme” options
Flagsmith application showing the remote config toggle
Flagsmith application showing the remote config toggle
Home screen of application with just the “dark theme” option
Home screen of application with just the “dark theme” option
Home screen of application in dark mode, and just the “dark theme” option
Home screen of application in dark mode, and just the “dark theme” option
Home screen of application in dark mode with “light theme” and “dark theme” options
Home screen of application in dark mode with “light theme” and “dark theme” options
Home screen of application with “light theme” and “dark theme” options
Home screen of application with “light theme” and “dark theme” options

Next steps

This step-by-step guide is just scratching the surface, by now it is very clear that remote configs don’t need to be just a boolean flag like on and off. It can have string, array, or other kinds of values. The string could be used to change things like button colors on the fly and with a simple array, we just saw a usage to change the number of available themes. An array can be easily used to change for example the bottom navigation with a similar approach.

Conclusion

We have seen how to create a remote config to control the number of themes dynamically on a mobile app built with React Native and expo. I hope this has sparked multiple ideas for you that you want to try, maybe you want the main navigation of your application to be a remote config or the menu items a logged-in user can be changed without a need to change any code.

Ship features with confidence. Flagsmith lets you manage features flags and remote config across web, mobile and server side applications.