Managing State in React Native With Redux Toolkit
Tags: javascript, redux, react, reactnative
Published: 2022-07-20 10:38:00

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.


<figure>
  <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dxsnddu5fwwnvvz9sybs.jpg">
  <figcaption>state flow in a Redux-managed React  application</figcaption>
</figure>


## 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](https://nodejs.org/en/) LTS >= v14.x.x (v16.14.2 recommended).
- A package manager like npm or [yarn](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable) installed.
- [Expo CLI](https://docs.expo.dev/get-started/installation/) 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](https://docs.expo.dev/) to create and run the project. 



Run the following commands in your local machines terminal:
```shell
expo init redux-toolkit-guide

cd redux-toolkit-guide
```
For the template, select ‘— *Managed Workflow*—*blank’.*

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](https://reactnavigation.org/docs/getting-started) for the latest installation instructions.
```shell
yarn add @react-navigation/native

expo install react-native-screens react-native-safe-area-context
```
You can find the app's complete source code in this [GitHub repo](https://github.com/theadultnoble/redux-toolkit-guide/tree/master).
### 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.

```javascript
//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,
  },
});
```
HomeScreen.js


Override **App.js** with the following code:
```javascript
//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 />;
};
```
App.js

Run `expo start` in your terminal to start the app:




<figure>
  <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1u7kjjzlk5fgxhvdwiwm.jpeg">
  <figcaption>Sample React Native color generator app</figcaption>
</figure>


## Setting Up the Redux store

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

```bash
npm install @reduxjs/toolkit react-redux
```

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](https://redux.js.org/understanding/history-and-design/middleware). 

Inside **store.js** create a redux store:
```javascript
import { configureStore } from "@reduxjs/toolkit";

export const store = configureStore({
  reducer: { },
});
```
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:
```javascript
//App.js

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

export default () => {
  return (
    <Provider store={store}>
      <App />
    </Provider>
  );
};
```
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:
```javascript
//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;
```
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`:
```javascript
//store.js
import colorSlice from "./colorSlice";

export const store = configureStore({
  reducer: {
    color: colorSlice,
  },
});
```
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:
```javascript
//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;

```
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.


<figure>
  <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2kvnpgvwl575ngfxluj9.png">
  <figcaption>React Native color generator app</figcaption>
</figure>


## 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](https://redux.js.org/introduction/getting-started) for further research.