A Complete reference guide to Redux: State of the art state management

Redux. The Complete Reference Guide

Redux. The Complete Reference Guide

Do you find Redux confusing? Do you want to master the redux fundamentals and start using it effectively with your favorite frontend framework? If so, you come to the right place. In this article we will go over every bits and pieces of redux so you can really understand what’s going on behind the scene.

In this tutorial we will discuss,

  • Redux core concepts (store, reducer, action) 🎯
  • React/Redux application structure ⚙️
  • Writing clean code with redux hooks 🧱
  • Best practices for clean code in redux ⚛️

Why do we need redux? 

Let’s say we are building a complex UI like the picture below.

The Structure of the App Interface. UX

The Structure of the App Interface. UX

We want to sync different parts of our application. If a user interacts with the big card component the application has to update the small card and navbar components.

Managing states and syncing all the components requires writing a lot of code. That’s why we use state management libraries such as redux. Redux can be used with frameworks like React, Vue, Angular as well as vanilla javascript.

Redux Core Concepts: 

In redux architecture we have three basic components.

  1. Store
  2. Reducers
  3. Actions

Store: The store is where we save our current application state. All the frontend UI components have access to the store. Think of the store as a database for the frontend components.

Components Accessing Store

Components Accessing Store

We can put any type of objects in our store. For instance let’s say we are building a TaskList application.  In this case our application state will contain the user information and tasks associated with that user. So our store might look something like this

Now let’s say some user interaction happens and a component in our application needs to update this store. We do not directly mutate this store. Redux is built on functional programming principles. Mutating the store directly can cause side effects. That’s why we have pure functions that take in the current store as a parameter and return an updated store. These functions are called reducers. 

[ Learn more about functional programing here ]

So our reducer look something like this

However, how does this reducer function know which part of the store needs to be updated? Well, reducer function also takes in another parameter called action. The action object contains information about what to update in the store. So our action objects can look something like this

UI components dispatch (it’s a fancy way of saying calling a function with an action object as parameter) an action to reducer and reducer updates the store.

How the Reducer works

How the Reducer works

Let’s see this behavior in action. I created a new react app and created two new files called reducer.js and store.js in the root directory.

👉 Click here for complete code example

The Structure of Redux Tutorial

The Structure of Redux Tutorial

Let’s make a simple reducer function.

We will take care of the implementation details later. Let’s write the store.js file.

We can now go to the index.js file and dispatch actions.

We imported the store and called dispatch method with an action object. Now if we look at the console log we can see that our reducer code is being executed.

 Console log. Reducer's code is being executed

Console log. Reducer’s code is being executed

We first dispatched an action with type property equals ADD_NEW_TASK. So the reducer executed the code block inside the first case statement. After that we dispatched an object with type equals REMOVE_TASK and the reducer executed the code inside the second case statement. Using case statements is the widely used pattern for reducer function.

Now that we have this in place let’s implement some code so that the reducer function will update the store.

Notice that we use spread operator and return a new array every time we add a new item. We follow the immutability principle here. If we decide to mutate the state itself then it will be hard to backtrack and debug our code when our code base gets more complicated.

Now let’s go back to our index.js file and add the following code

This codeblock will initiate an event listener. We will be able to console log all the changes happening to store. In the components on our application we have event listeners like this that updates the component UI when a particular change is detected.

In some cases we might want to stop this event listener to prevent memory leaks. We can do so by creating an unsubscribe call show below.

In the example above the listener will stop and will not log the second dispatched action.

👉 Find the complete code up to this point here

That’s all there is to basic redux. Redux is a very small, simple but powerful library. Next let’s look at how we can use redux in our react application.

Adding Redux to React Project

I added two new components in our App component. A TaskForm component to create new tasks and a TaskList component to show tasks lists.

We can make redux interact with these components with listeners as demonstrated earlier. However, there is a better way. There is a library called react-redux that makes the process even easier.

Let’s install it 🧙‍♂️

Now we have to make the following changes in our index.js file.

We imported the provider component and wrapped our App  component with it. We are also providing the store object as a property in the Provider. By doing this every component under provider will be able to access the store.

Now we want to dispatch actions from our TaskForm component. Previously, we used to do it with redux higher order components. However, now there is a react hook for it which makes it a piece of cake to implement. Here’s the code below,

All we did is bring in the useDispatch hook and execute it on button click with our payload. That’s it.

Now, in the TaskList component let’s take a look how to access the store.

Components update in action

Components update in action

We used the use selector hook to access the store and got the updated store. Now we are able to add new tasks and see the components update.

Additionally we can implement deleting a task functionality in the TaskList.

We used the useDispatch hook again in this component and dispatched the REMOVE_TASK action. That’s all there is to it.

Get the code up to this point here

Next, we will look at how we can refactor this code and apply some best practices.

Redux best practices

Keeping the action types separate: It is a best practice to separate action types and consolidate them into a separate file This way we have to change them into one place if we have to. Let’s do that now.

We create a new file called actionTypes.js in our root directory. Then we write the following code.

Now let’s use this export in our reducers and dispatch.

Refactoring all dispatch actions:  Another best practice is to keep all the dispatch actions into one location. Let’s see how it is done.

Let’s create a new file actions.js in /src directory.

Creating a new file `actions.js` in `/src` directory

Creating a new file actions.js in /src directory

Now let’s create our actions inside actions.js file.

As you can notice this is just returning the dispatch payload. Now we can use these functions instead of defining the object when dispatching from our components. We’ll update our components like below

💾 You can find the code up to this point in the following link.

Structuring multiple stores: 

Let’s see how we can structure our redux code for better readability and separation of concerns. It is always a good idea to separate the UI layer from the store.

Structure of Redux Code

Structure of Redux Code

As our application grows we can have multiple folders inside the store. We usually write our business logic inside redux. Therefore, each folder becomes a separate domain model.

Each Folder is a Separate Domain Model

Each Folder is a Separate Domain Model

I hope this article has helped you better understand redux. For content like this please subscribe to our newsletter 🙂 That’s all for today.

About the author

Stay Informed

It's important to keep up
with industry - subscribe!

Stay Informed

Looks good!
Please enter the correct name.
Please enter the correct email.
Looks good!

Related articles

26.03.2024

An Introduction to Clustering in Node.js

Picture your Node.js app starts to slow down as it gets bombarded with user requests. It's like a traffic jam for your app, and no developer likes ...

15.03.2024

JAMstack Architecture with Next.js

The Jamstack architecture, a term coined by Mathias Biilmann, the co-founder of Netlify, encompasses a set of structural practices that rely on ...

Rendering Patterns: Static and Dynamic Rendering in Nextjs

Next.js is popular for its seamless support of static site generation (SSG) and server-side rendering (SSR), which offers developers the flexibility ...

No comments yet

Sign in

Forgot password?

Or use a social network account

 

By Signing In \ Signing Up, you agree to our privacy policy

Password recovery

You can also try to

Or use a social network account

 

By Signing In \ Signing Up, you agree to our privacy policy