DEV Community

Cover image for Managing State in React Native With Redux Toolkit
Noble Okafor
Noble Okafor

Posted on • Updated on

Managing State in React Native With Redux Toolkit

When developing robust web or mobile applications(apps), handling state internally, as is the norm with React Native components, isn't always ideal. If done improperly, it can quickly become very messy. A library tool like Redux is advised in these circumstances.

This tutorial will teach you how to use Redux Toolkit to manage the state flow in a React Native app.

What is Redux?

Redux is a Javascript global state management library designed to act as a central store for managing application state. Redux helps you build apps that behave consistently across all environments by tracking all changes made to the app state.


state flow in a Redux-managed React application

What is Redux Toolkit?

Redux Toolkit is Redux's official toolset for developing efficient React-Redux apps. It was designed to simplify the writing of common Redux logic and resolve the usual difficulties of using the core Redux library.

such as:

  • Setting up the Redux store
  • Creating reducer state slices
  • Writing immutable state updating code

Redux Glossary

Action

An Action is an object that indicates a desire to modify a state in the Redux store. Actions must include a payload and a type attribute that specifies the state change's nature. Reducers are required to carry out Actions.

Reducer

A Reducer is a pure function that takes two arguments; the current state and an action to return a new state result. Reducers do not modify the original state directly; rather, they make a copy of the state and modify that.

Dispatch

A "dispatch function" is a function that accepts either a synchronous or asynchronous action object and sends it to a reducer for execution.

Slice

A collection of reducers and actions that work together to implement a single app feature.

Store

According to the official Redux documentation, a store is an object that holds the app's entire state tree. Redux can only have a single store in an app.

Using Redux Toolkit with React Native

Prerequisites

  • Node.js LTS >= v14.x.x (v16.14.2 recommended).
  • A package manager like npm or yarn installed.
  • Expo CLI installed.
  • Knowledge of Redux concepts.

NOTE: This article is not a tutorial on React Native and will not be focusing on React Native concepts.

Project Setup

The app you will build will be a random color generator, and to keep things simple, you will be using Expo CLI to create and run the project.

Run the following commands in your local machines terminal:

expo init redux-toolkit-guide

cd redux-toolkit-guide
Enter fullscreen mode Exit fullscreen mode

For the template, select ‘— Managed Workflowblank’.

Install the app's necessary dependencies, including @react-navigation/native, react-native-screens, and react-native-safe-area-context.

See the official React Navigation library documentation for the latest installation instructions.

yarn add @react-navigation/native

expo install react-native-screens react-native-safe-area-context
Enter fullscreen mode Exit fullscreen mode

You can find the app's complete source code in this GitHub repo.

Building the App Interface

Open the redux-toolkit-guide app in a code editor and create the following file structure.

  1. Create a src folder in the project's root.
  2. Inside src create a store folder.
  3. Inside store, create a colorSlice.js and store.js file.
  4. Create a screens folder inside src.
  5. Inside screens, create a HomeScreen.js file and import the code below.
//HomeScreen.js
import React from "react";
import { StatusBar } from "expo-status-bar";
import {
  Text,
  View,
  StyleSheet,
  TouchableOpacity,
  FlatList,
} from "react-native";

const HomeScreen = () => {
  return (
    <View>
      <StatusBar style="dark" />
      <TouchableOpacity
        onPress={() => //empty anonymous function}
        style={styles.button}
      >
        <Text style={{ fontSize: 20 }}>Generate Random Color</Text>
      </TouchableOpacity>
      <FlatList
        keyExtractor={(item) => item}
        data={color}
        style={{ marginTop: 15 }}
        renderItem={({ item }) => {
          return (
            <View
              style={{
                backgroundColor: item,
                height: 150,
                width: 150,
                alignSelf: "center",
                margin: 10,
              }}
            />
          );
        }}
      />
    </View>
  );
};

export default HomeScreen;

const styles = StyleSheet.create({
  button: {
    alignSelf: "center",
    borderWidth: 1,
    borderRadius: 10,
    padding: 10,
    marginTop: 20,
  },
});
Enter fullscreen mode Exit fullscreen mode

HomeScreen.js

Override App.js with the following code:

//App.js
import * as React from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import HomeScreen from "./src/screens/HomeScreen/HomeScreen";

const Stack = createNativeStackNavigator();

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

export default () => {
  return <App />;
};
Enter fullscreen mode Exit fullscreen mode

App.js

Run expo start in your terminal to start the app:


Sample React Native color generator app

Setting Up the Redux store

Install the Redux toolkit and React-Redux packages in your project:

npm install @reduxjs/toolkit react-redux
Enter fullscreen mode Exit fullscreen mode

Redux toolkit creates a store using the configureStore API in place of the createStore from core Redux.configureStore automatically sets up the Redux DevTools Extension and some middleware.

Inside store.js create a redux store:

import { configureStore } from "@reduxjs/toolkit";

export const store = configureStore({
  reducer: { },
});
Enter fullscreen mode Exit fullscreen mode

colorSlice.js

The store holds a single root reducer object for all the state slices in the app.
Now wrap the app component in App.js with the store using the React-Redux Provider. This ensures the Redux store is at the topmost level and is available to the entire React Native app:

//App.js

import { store } from "./store/store";
import { Provider } from "react-redux";


export default () => {
  return (
    <Provider store={store}>
      <App />
    </Provider>
  );
};
Enter fullscreen mode Exit fullscreen mode

App.js

Creating Redux Toolkit Slices

Next, you will create a state slice to handle all action and reducer functions relevant to generating a random color in the app. Importing and calling createSlice, define inside it;

  • a name to identify the slice.
  • an initialState value. This specifies the state on the first app render (similar to the useState hook).
  • a reducer function to determine how the state is to be updated. With the spread operator, update the state.value with the result of the randomRgb().

When writing core Redux logic, it is essential to avoid directly mutating the state value. But, with createSlice available through Redux Toolkit, you can write mutating code in reducers and have it converted into immutable copies:

//colorslice.js
import { createSlice } from "@reduxjs/toolkit";

const initialState = {
 colors generated
  value: [],
};

//A function to generate random RGB values
const randomRgb = () => {
  const red = Math.floor(Math.random() * 256);
  const green = Math.floor(Math.random() * 256);
  const blue = Math.floor(Math.random() * 256);

  return `rgb(${red}, ${green}, ${blue})`;
};

//State slice
export const colorSlice = createSlice({
  name: "color",
  initialState,
  reducers: {
    setColor: (state) => {
      state.value = [...state.value, randomRgb()];
    },
  },
});

// Action creators are automatically generated for each case reducer function 
export const { setColor } = colorSlice.actions;

export default colorSlice.reducer;
Enter fullscreen mode Exit fullscreen mode

colorSlice.js

NOTE: Only write mutating code using the createSlice or createReducer APIs.

Redux toolkit allows you to create action objects automatically. Above, you have set the case functions defined in our reducer to colorSlice.actions. The name of the reducer will be used as the action type when creating an action creator.

Afterward, import and add the created slice to the root reducer of the store:

//store.js
import colorSlice from "./colorSlice";

export const store = configureStore({
  reducer: {
    color: colorSlice,
  },
});
Enter fullscreen mode Exit fullscreen mode

store.js

useSelector and useDispatch

You have successfully set up a Redux state management system. Now, you need to be able to read the current state inside HomeScreen.js and dispatch an action to the reducer.

Use the useSelector hook to access the redux state and the useDispatch hook to dispatch actions:

//HomeScreen.js
import { useDispatch, useSelector } from "react-redux";
import { setColor } from "../../../store/colorSlice";

const HomeScreen = () => {

  const color = useSelector((state) => state.color.value); //reading the state 
  const dispatch = useDispatch();

  return (

      <TouchableOpacity
        onPress={() => dispatch(setColor())} //Dispatch action

      >
        <Text style={{ fontSize: 20 }}>Generate Random Color</Text>
      </TouchableOpacity>

        <FlatList
        data={color}
      />
  );
};

export default HomeScreen;

Enter fullscreen mode Exit fullscreen mode

HomeScreen.js

Above, you have imported useDispatch and useSelector from React-Redux. You have also imported the created setColor reducer. Reading the current state with state.color.value, you set its value as the data entry for the Flatlist. Then, by calling useDispatch() as dispatch and passing setColor() as its argument, you have sent the action to the appropriate reducer case.

That's a wrap! Your React Native app can now generate random colors.


React Native color generator app

When to Use Redux?

The app you built is ideally too basic to use a state manager like Redux. However, this tutorial aims to introduce Redux Toolkit in the most basic way possible.

So when should you use Redux?

  • When there's a considerable amount of data changing over time
  • When you need to track state changes
  • When dealing with deeply nested components, and passing state becomes problematic
  • When multiple components require access to the same piece of state

Conclusion

This tutorial covered what Redux and Redux Toolkit are and the basic terminologies. It also covered the steps for integrating Redux Toolkit into a React Native application;

  1. Creating a store with configureStore
  2. Providing that store to the app
  3. Creating reducer slices with createSlice
  4. and reading and updating the state with useSelector and useDispatch

I recommend visiting the official Redux documentation for further research.

Top comments (0)