Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
When and why should I use redux?
3.
What is Redux in React JS?
4.
Redux Architecture
4.1.
Store
4.2.
Actions
4.3.
Reducers
5.
Background Concepts
5.1.
State management
5.2.
Immutability
6.
Redux Terminology
6.1.
Actions
6.2.
Reducers
6.3.
Store
6.4.
Dispatch
6.5.
Selectors
7.
Redux Principles
8.
Redux Application Data Flow
8.1.
Initial setup
8.2.
Updates
9.
Frequently Asked Questions
9.1.
Is Redux front-end or back-end?
9.2.
Is Redux a state or store?
9.3.
Is Redux an API?
9.4.
What are Hooks in Reactjs?
9.5.
What is the flow of Redux?
9.6.
How and why is Redux immutable?
10.
Conclusion
10.1.
Recommended Reading
Last Updated: Mar 27, 2024
Medium

React Js - Redux: Basic Concepts and Data Flow

Author Reet Maggo
0 upvote

Introduction

Redux is an open-source library for Javascript that manages and updates application state, using events called "actions". It is like a centralized store for the state used across an entire application, with rules that ensure that the state can only be updated predictably. It is usually used with libraries like Angular or React to build user interfaces. 

Redux: Basic Concepts and Data Flow

In this article, we will discuss Redux in React js. We will also discuss Redux: Basic Concepts and Data Flow, Redux principles, terminology, and when and why should we use Redux. 

Also See, Dropdown in React JS

When and why should I use redux?

Redux in React Js is quite useful when:

  • There are large amounts of application states required in several places in the app.
  • The application state is frequently updated.
  • The logic for updating the state might be complex.
  • The codebase in the application is medium or large and worked on by a lot of people.

What is Redux in React JS?

Redux in React JS helps manage the "global" state, which is needed across several parts of the application. The tools and patterns offered by Redux in React JS make it convenient to understand how, where, and why the state in an application is being updated and how its logic will act after those changes. Redux also guides users towards a more predictable and testable code. 

If you want to get familiar with some basic definitions in Redux, you can visit the Coding Ninjas Guide to Redux for a kickstart.

Redux Architecture

Redux architecture is a widely used architectural pattern for making web applications. It is used when there is a need for managing complex states. Redux is based on flux architecture. You can also use React with angularJS and vanilla JS, but it works effectively with React.

redux architecture

Redux follows the unidirectional data flow, i.e., the changes made in the data are handled in a consistent way. Therefore we can efficiently manage the state of the application, making the understanding of data flow a lot easier. Below are the components of the redux architecture.

Store

While making a web application, we need data for various components; the main concept of ‘Store’ refers to the data rather than being scattered across various components stored in one place.

 A ‘Redux Store’ refers to a central container that holds the state of the application. It is the place where the whole data of an application is stored. Therefore it becomes a lot easier for managing and synchronizing the data of the application.

Actions

The plain javascript objects are referred to as actions. They are used to represent the reason for changing the application’s status, Actions majorly describe user interaction, time events, or API responses.

Reducers

Pure functions in javascript that represent how the state of the application is to be changed in response to actions. Reducers accept an action and the current state as its input, and a new state is returned on the basis of the type of action.

We should remember that the reducers must not change the existing state. Rather new state objects are returned and created. 

Background Concepts

Below are the terms and concepts that need to be learned for Redux:

State management

Take an example where the React counter component tracks some number in the component state and increments it when the given button is clicked:

function _counter()
{
  // The state is a counter value
  const [counter, setCounter] = useState(0)

  // The action is when code causes the state to update when something happens
  const increment = () =>
  {
    setCounter(prevCounter => prevCounter + 1)
  }

  // View: the UI definition
  return
  (
    <div>
      Value: {counter} <button
      onClick={increment}>Increment</button>
    </div>
  )
}


The application has:

  • The state that drives this application;
  • The view, which is a description of the User Interface based on the present state
  • The actions are the events that trigger updates in the state and occur in the application based on input.

 

This is a great example of one-way data flow:

  • The state describes how the condition of the application is at a given point in time.
  • Based on that state, the User Interface is rendered.
  • When some action occurs (e.g., the user clicks a button), the state is updated.
  • Based on the new state, the UI re-renders.

 

However, when multiple components need to share and utilize the same state, the simplicity is broken down, mainly if the components are situated in various application parts. This issue can sometimes be resolved by "lifting state up" to parent components, but the method might not always help.

So a method for users to solve this issue is extracting such shared states from the components and putting them outside the component tree at a centralized location. 

The component tree will thus become a big "view", and all components will have access to the state or thus trigger actions, irrespective of the location of the components in the tree.

The basic idea behind Redux is thus a centralized space that can contain the global state in an application and fixed patterns for when the state is being updated so that the code is more predictable.

Immutability

Mutable objects are the ones that are changeable and immutable means something that cannot be changed. Objects and arrays in JavaScript are mutable by default. Users can change the contents of an object’s fields after creating them. The same applies to arrays too:

const _obj = { x: 1, y: 2 }

// The contents of the object have changed, but it is still the same object outside
obj.y = 3

const arr = ['x', 'y']

// Similarly, the contents of array can be changed too
arr.push('z')
arr[1] = 'a'


The above-shown concept is known as mutating the object or array. The memory has the same object or array reference, but the contents inside them will have changed.

The code will have to make copies of the already existing arrays or objects and then modify the copies to update values immutably.

This can be done using the array or object spread operators in JavaScript and also using array methods returning new copies of the array instead of mutating the original array:

const obj =
{
  x: {
  
      // Safe updation of obj.x.z requires us to copy each piece
      z: 3
    },
  y: 2
}

const obj2 =
{

  // Copy obj
  ...obj,
  
  // Overwrite x
  x:
  {
  
    // Copy obj.x
    ...obj.x,
    
    // Overwrite z
    z: 42
  }
}

const arr = ['x', 'y']

// New copy of arr is created with "z" appended to its end.
const arr2 = arr.concat('z')

// Or, the program could use a copy of the original array:
const arr3 = arr.slice()

// Mutating the copy
arr3.push('z')


All state updates in Redux are expected to be done immutably. 

Redux Terminology

Below are some of the important Redux terms that need to be understood before proceeding further:

Actions

Actions are JavaScript objects with a ‘type’ field and can be considered as events describing something that happened in the app.

The ‘type’ fields should be strings giving such actions some descriptive name, such as "todos/todoAdded". The strings are usually written as "domain/eventName", meaning first the action category and then specifically the thing that happened.

Action objects could have additional information about the event in other fields. Conventionally, this additional information is put in a field known as payload.


An example of a typical action object is given below:

const addTodoAction =
{
  type: 'todos/todoAdded',
  payload: 'Buy sugar'
}

Reducers

Reducers are functions receiving the present state and action objects. They can be considered event listeners that handle events according to the received action (event). Reducers decide how the state will be updated and return the new state: (state, action) => newState. 

Reducers should always follow these rules:

  • The value of the new state should be calculated only based on the state and action arguments.
  • The existing state must not be modified. Instead, reducers should copy the existing state and make changes to make immutable updates.
  • No other side effects must be caused, and asynchronous logic, calculating random values and similar activities must be avoided.
     

Reducer function logic follows these steps:

  • Checking whether the reducer cares about this action or not
  • If yes, copy the state, update it with new values, and return it
  • Otherwise, return the existing state.
     

To decide the new state, reducers could use any logic such as if/else, switch, or loops.

const initialState = { value: 0 }
function Reducer(state = initialState, action)
{

  // Checking whether the reducer cares about this action or not
  if (action.type === 'counter/incremented')
  {

    // Make a copy of `state` if yes
    return
    {
      ...state,

      // Updating copy with new value
      value: state.value + 1
    }
  }
  
  // Else, return the existing state
  return state
}

Store

A store is an object where the present state in the Redux application lives. It is created by passing in a reducer and has a method called getState that returns the current state value:

import { configureStore } from '@reduxjs/toolkit'
const store = configureStore({ reducer: counterReducer })
console.log(store.getState())

// {value: 0}

Dispatch

Dispatching actions can be considered as triggering events in the application.

The dispatch method in the Redux store provides a way to update the state by calling store.dispatch() and passing an Action. The reducer function of the store will run, and the new state value will be saved inside. Then, getState() can be called to retrieve the updated value:

store.dispatch({ type: 'counter/incremented' })
console.log(store.getState())

// {value: 1}

Selectors

Selector functions can extract specific parts of information from a store state value. As an application grows bigger, this can help avoid repeating logic as different parts of the app need to read the same data:

const selectCounterValue = state => state.value
const currentValue = selectCounterValue(store.getState())
console.log(currentValue)

// 2
selectors in redux

Redux Principles

Redux is a valuable tool to organize application states and very predictably contains states for JavaScript applications. Its design can be summarised as:

  1. A single store is used to contain the application’s global state, and any data must exist in only one location instead of being duplicated several times. Debugging is thus made easier, along with ease of inspecting app state and centralizing logic.
  2. The state can only be changed by dispatching an action. This ensures that the UI doesn’t overwrite data accidentally, and the reason behind the state update is easier to trace. Actions being plain JavaScript objects can be logged, stored, serialized, and replayed later to debug, test, and so on.
  3. Reducer functions are used to define how the state tree is updated based on actions. Reducers take the present state and an action and return to the next state. Reducers can be split like other functions, and these smaller functions could be used for writing reducers that are reusable for common tasks.

Redux Application Data Flow

The article briefly discussed unidirectional data flow earlier and the sequence of steps to update the app. These steps can be explained in more detail for Redux:

Initial setup

  • A root reducer function is used to create a Redux store.
  • The return value after the store calls the root reducer is saved as its initial state.
  • The UI on being rendered has its components access the present state of the Redux store and use it to decide what must be rendered.

Updates

  • Some action occurs (e.g., a user clicking a button)
  • An action is dispatched to the Redux store by the app code.

e.g., dispatch({type: 'counter/incremented'})

  • The store reruns the Reducer function with the previous state and the present action. The return value is then saved as the new state.
  • The store notifies all subscribed parts of the UI about updates.
  • Every user interfaces component checks if the parts of the state they need have changed.
  • Every component whose data has been changed forces a re-render with the new data to update what is shown on the screen.

Frequently Asked Questions

Is Redux front-end or back-end?

Redux can be used with user interfaces for the client-side (front-end), and since it is just JavaScript, it can also be used at the back-end on the server-side.

Is Redux a state or store?

Redux is a JavaScript state management pattern and library that uses a store to handle and maintain the application state.

Is Redux an API?

No, Redux is not an API. It is a state management pattern and library for JavaScript applications.

What are Hooks in Reactjs?

In React.JS, hooks are special functions that allow you to add state and other cool features to your functional components. They make it simple to work with stateful logic without using class components. 

What is the flow of Redux?

The flow of data in Redux is unidirectional, meaning the application data follows a one-way binding data flow. As the application becomes complex and growing, issues and new features are harder to reproduce if the user doesn’t have control over the app state.

How and why is Redux immutable?

Redux doesn’t mutate the state but creates a copy of the object, where the state is updated. This means that Redux is immutable which makes it safer to handle data. Debugging requires the reducers to have no side effects so that the user can jump between different states correctly, which is provided by immutability.

Conclusion

In this article, we learned about Redux in React js. We have also discussed Redux: Basic Concepts and Data Flow, Redux principles, terminology, and when and why should we use it. You can read more such descriptive articles on our platform and take your coding journey to the next level. 

Recommended Reading

 

You can also consider our React Js Course to give your career an edge over others. Until then, All the best for your future endeavors, and Keep Coding.

Live masterclass