Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
Starting with an app concept
3.
Defining App Structure
4.
Understanding the Reducer Function
5.
Creating a simple store and dispatching actions:
6.
Changing the State of the store to update it
7.
Frequently Asked Questions
8.
Key takeaways
Last Updated: Mar 27, 2024

Redux States, Actions and Reducers

Author Reet Maggo
1 upvote

Introduction

After learning about Redux concepts and data flow, we learned how Redux gives us a single central place to put the global app state and thus helps us build maintainable apps. We also discussed core Redux concepts like dispatching action objects and reducer functions that return new state values.

We will learn how the state, reducers and actions work together with the help of an app concept described below.

Starting with an app concept

Below is the component structure of the application concept we have taken as an example:

Defining App Structure

  • The App will have the ‘Blog’ and the ‘Homepage’ components, where the blog further has a component named ‘Newest Blogs’ to show the most recent blogs (the data for which is received from an external source).
  • The user might also want to show some of the ‘Newest Blogs’ in the sidebar on the Homepage.
  • Data can be taken from an external source, stored in the state of the blog component and be passed down as props. The App can then reach out for the data on the home page, get the data, store it in the state, and pass it down as props. We can see how duplicating the code is not the best method to adopt in such a situation.
  • The other way can be to pass the data from the ‘Blog’ to the App.js and around the sidebar, which is very convoluted.

In such situations, Redux acts as a central data store to share data between components without making the process complicated.

If the blog component wants some data, it can reach out to this central store and pass it down to the components. If the ‘Side bar’ wants the same data, it can also reach out to the central store. This entire process is simple, and there is no need to duplicate the state multiple times. Changing the data too can be done through these components. 

For example, the ‘Side bar’ can change the data, and the updated data is passed on to the ‘Blog’ and elsewhere in the application.

However, the components themselves cant directly edit the data as it is unsafe and may result in unpredictable code.

If a component wants to make a change to the central data store safely such that the code is predictable and easier to track and debug:

  • First, decide the change.
  • Then dispatch an action, describing the changes needed to be made (e.g.: ‘addpost’ to add a new item to the data)
  • With the action, an optional payload can be passed. The payload can be any sort of data that may be needed to be passed along.
  • The action is passed to the reducer. The reducer then looks at the type of the data and takes it to the central data store, and updates the state.

Hence, it is the reducer that updates the data store, not the components directly. This process may be a little complex, but it helps in making apps much more manageable.

Understanding the Reducer Function

The Reducer is a function that interacts with the store to change its state. The store can be considered a warehouse for storing the states, and the Reducer can be considered the guard of the warehouse since only the Reducer can go inside and edit the state. When actions are dispatched somewhere else in the program, the guard (Reducer) receives them and then uses these actions to update the state.

The state is always updated from a single place, i.e., the reducer. Actions are handed to the Reducer, and the Reducer changes the store depending on the kind of actions being passed.

The reducer function and the store are coupled together so that when a store is created, we pass a single reducer function as a parameter to the store. In this case, the store will know which reducer will handle those changes, making it more predictable.

Creating a simple store and dispatching actions:

//storing from the Redux library
const { createStore } = Redux

/*creating an initial state to be used as the default value for reducer function later*/
const initialState={
  todos:[ ]
  posts:[ ]
}

/*creating reducer (a function to interact with the store, with two parameters-state and action)*/
function reducer1(state=initialState, action)
{
  //logging the action to the console
  console.log(action, state)
}

//creating store
const store=createStore(reducer1);

//adding a new todo using an action ‘add_todo’

//adding optional load of  data called todo

const todoAction={ type: 'add_todo', todo: 'buy milk'}
/*being an action, it is set equal to a JS object, with a type property*/

//creating store to dispatch an action, passing the action in the parameter in the reducer function
store.dispatch(todoAction)

Now that we have learned how to dispatch actions, we will modify the ‘reducer1’ function, which you can check out in the following code. Here we will change the state of the store to update it.

Changing the State of the store to update it

//storing from the Redux library
const { createStore } = Redux

/*creating an initial state to be used as the default value for reducer function later*/
const initialState={
  todos:[ ]
  posts:[ ]
}

/*creating reducer (a function to interact with the store, with two parameters-state and action)*/
function reducer1(state=initialState, action)
{
  /*checking the type of function received to manipulate the state accordingly*/
    if(action.type== ‘add_todo’)

     {

         //updating state

         return
        {

              //returning new state of the store

              todos: [...state.todos, action.todo]

         }

      }
}

//creating store
const store=createStore(reducer1);

//adding a new todo using an action ‘add_todo’

//adding optional load of  data called todo
const todoAction={ type: 'add_todo', todo: 'buy milk'}
/*being an action, it is set equal to a JS object, with a type property*/

//creating store to dispatch action, passing the action in the parameter in the reducer function
store.dispatch(todoAction)

By looking at the reducer function in the new code, we understand how we can change the store’s state or update it.

However, if we run this code now, nothing much will happen since we are not logging anything into the console. Further, you should learn to subscribe to changes to store and then react to them discussed in our next article.

Frequently Asked Questions


Q1. What is meant by dispatch and payload in react?

The dispatch function provided to us by Redux allows us to send actions to the state or reducers, and payload refers to the message or the contents of an action.


Q2. Why are reducers used in Redux?

Redux relies greatly on reducer functions that take the current state and execute the next state. Reducers determine changes to the app state by receiving actions and deciding the new state accordingly.


Q3. How many Reducers do I need in Redux?

Redux applications only have one reducer function, the ‘Root Reducer’ passed to createStore later. This Reducer is responsible for handling all the dispatched actions and calculating the new state result every single time.


Q4. Explain actions and their type field.

Actions are plain JS objects containing information and are also the only sources of information for the store. Actions have a type field that tells about the kind of action that is needed to be performed.

Key takeaways

In this article, we learned about Reducers, states and actions in Redux in a simple example app, with the help of code snippets.

You can go to Coding Ninjas Studio to try and solve more problems for practice. Send this blog to your friends if you found it helpful! Until then, All the best for your future endeavours, and Keep Coding.

Live masterclass