Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

React Native with Redux: how to use it?

Tiago Madeira

February 23, 2024

Min Read
React Native with Redux: how to use it?

What is redux and why use it ?

Redux is a javascript library made to help you manage the state of your application. It does that by providing the developer with a centralized place called the store, where the state is saved and modified through actions and reducers. This centralized place enables you to share the state between multiple screens and to know exactly where and how the state is being modified. This is particularly useful in growing applications that are too large for the developers to have full knowledge of the data flows and, consequently, become bug prome.

blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo

How to use redux

As said above, redux uses a combination of actions, reducers and the store to manage the application state. To understand and learn redux, you need to know how these abstractions works. Let's start!

  • The State

Very lightly, the application state is all the information that the application uses and/or modifies. Having a centralized state and a predictable way of modifying it can enable applications to be coherent with the information that they show to the users. This is particularly useful for large single page applications.

  • Actions and reducers

Actions and reducers together modify the state. Precisely, actions determine what is being modified and where. Reducers specify how it is being modified. By analyzing the layout at the beginning of the blog post, we will need three actions: INCREMENT, DECREMENT, and CHANGE_BY_AMOUNT. Actions are objects with a type and a payload attribute. The type is the action's identifier, and the payload is all the information that the reducer will need to modify the state. The first two actions will only decrement or increment the counter amount by 1, so we only need to define two objects with the attribute type, and the reducer will handle the rest. The third action must have a payload to specify how much we want to increment or decrement the counter. Declare your actions in a separate file called Actions:


As you can see, it is pretty simple. Next, we define the initial state. This is done in another file along side with the reducer:

We set the initial state to have an object named counter with the attribute amount, starting at 0. You can also see that the initial state is a constant and not a variable, which appears to make no sense, but we will explain it to you later. Next, we build the reducer, which is a function that receives the current state and the action - as arguments - to produce the new state of the application. Here it is:


We must not mutate the state in the reducer. Why? In fact, the reducer should not modify the state object directly. Instead, it should create a new object, which will be the new state. React’s rendering engine compares the previous state object with the latest state object.

If you modify the state directly, React does not know what has changed, and it will have a flawed notion of the application state. You can start reading about this here. This is why, in the beginning, we declared the initial state as a constant and not as a variable, as we pretend the initial state object never to be altered.

  • The Store

The next step is to create the store. The store is the object where the state is saved. It is common practice to create the store and export it in a separate file. Check it below:


We create the store using the createStore() method from redux, which receives as argument the reducer function defined earlier. With the store, we can invoke actions with the dispatch method (will be shown later in this guide) to modify the state.

Now we make the store available by passing it to the Provider component that engulfs our SimpleCounter component. What the Provider component does is provide access to the store in the SimpleCounter component and all the components inside it.

The Provider component is imported from the react-redux library, which is the official binding library for react/react native and redux.See below how to do it:


blue arrow to the left
Imaginary Cloud logo

Connect your react components

Next, we want to connect our components to the redux store. We can do this by using the connect method from react-redux library in our SimpleCounter component file, like so:


We need to pass two arguments to the connect method: the component we want to connect (SimpleCounter) and a function that maps the application state to our component props.

Note that we only have access to the state object in the mapStateToProps function because we engulfed the SimpleCounter component with the Provider component.

The connect method is merging the object returned from mapStateToProps with the props of the SimpleCounter component to access the state.counter.amount value via this.props.amount.

The dispatch method also becomes available through props, and we can now import our actions and dispatch them inside the SimpleCounter component. Here’s the SimpleCounter component updated code:


blue arrow to the left
Imaginary Cloud logo

React Native state persistance

So now we have a centerlized store were the state is saved and modified in a predictable way through actions and reducers, but you might have noticed that the counter value returns to zero every time you refresh or exit the app, this is because right now the state is not being persisted and every time you open the application the reducer is defining the counter value to be zero (the initial state).

State persistance is important if you need to maintain certain information even when the user closes the application, like login tokens or some configuration settings. You can achieve state persistance in a React Native app by using the redux-persist library.

Redux persist saves the redux store into a local persistent storage and retrieves it every time the app is re-openned or refreshed. We are using an Android emulator, but redux-persist also works with IOS. Let's start by installing redux persist:

After that, modify the Store.js file, like so:


First import both persistStore and persistReducer methods from redux-persist library. Pass the reducer to the persistReducer method along side the persistConfig object to create a persistedReducer.

In the persistConfig object declare that you are going to use the AsyncStorage to persist the redux store which is an unscrypted key-value storage from React Native.

New call-to-action

Finally, call the persistStore method to ensure that our store is persisted. If you have a bigger project, you might not need to persist the entire state, in that case, you can use a 'Whitelist' and 'Blacklist' methodology in the persistConfig object to choose which reducers you want to persist, click here if you want to know more.

Last, in the App.js file import the persistedStore from Store.js and engulf the SimpleCounter with the PersistGate component to make sure that the app's UI is not rendered until the persisted state is retrieved and saved into the redux store.

blue arrow to the left
Imaginary Cloud logo

Redux toolkit

We have to mention the Redux toolkit, a library written by the redux developers to help create more efficient redux logic. Utilizing this library's functions will result in your code being more compact and simpler to read. Here is an introduction to some of those functions:

createAction()

Redux toolkit introduced us with a new way of creating an action. It works like this:

The createAction method receives the action type as an argument and returns an action creator function. We can then call this function and pass the payload as an argument to create the action object. You can also access the action type with the toString() method, like so, incrementAction.toString(). This method makes it so that we no longer need to declare the action types as constants reducing the boilerplate code significantly.

createReducer()

This is another method of the redux toolkit that aims to simplify our code. The method allows us to write reducers with the lookup table notation, enabling us to write a much cleaner code. The objects returned from the createAction() method can be used directly as the table keys. Following with the previous reducer logic, we have:


In addition to this, createReducer() also uses Immer to write reducers with simpler mutating logic. Immer translates all mutating operations into equivalent copy operations. So now, we can write our reducer like this:


Much simpler don't you think ?

configureStore()

The configureStore() function wraps around the createStore() method and creates the store setting up some standard configurations. Also, the method receives a configuration object instead of a group of functions so, when using it, you must pass the reducer inside an object associated to the reducer attribute. Like this:


Store configuration is a matter that we did not include in this blog post, but we felt that it was still important to mention so, if you want, feel free to explore it yourself. One more thing, if you want to integrate redux-persist and redux-toolkit in the same project you might have came across the error 'A non-serializable value was detected in an action' this is because redux-toolkit's configureStore() incorporates a serializable check on actions and redux-persist needs to pass a function inside them. One way you can solve this is importing getDefaultMiddleware from redux-toolkit and disabling the serializable check on redux-persist actions types. Like so:


You can find the discussion and the solution for this problem in this forum.

In short

There it is. The result should be a simple but functional counter app. We hope you learned how redux's abstractions work together and familiarized yourself with the dataflows that they create, so it becomes easier for you to start applying redux to your app. Additionally, redux is an independent library, so the logic you learned here would be the same if you wanted to integrate redux in a web application that uses react. Wish you the best of luck programming!

Grow your revenue and user engagement by running a UX Audit! - Book a call

Found this article useful? You might like these ones too!

blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
Tiago Madeira
Tiago Madeira

Computer science student and ImaginaryCloud part-timer. Eager to learn new technologies and techniques. Tennis and piano player.

Read more posts by this author

People who read this post, also found these interesting:

arrow left
arrow to the right
Dropdown caret icon