Decoding Redux: A Guide to State Management

Swatik Paul
4 min readJan 29, 2024

--

Redux has become an integral part of modern web development, particularly in the context of single-page applications (SPAs). It is a predictable state container for JavaScript applications, making it easier to manage and update the state of your application. In this blog, we will delve into the fundamental concepts of Redux: State, Actions, and Reducers.

Redux: A reliable state management solution for JavaScript applications

State in Redux

At the core of Redux is the concept of state. State represents the data or information that defines the current condition of your application. In a Redux application, all the state is stored in a single JavaScript object, often referred to as the “store.”

The store is a centralized hub for holding the state of your entire application. It provides a single source of truth, making it easier to manage and control the flow of data. Developers can access and update the state only through predefined actions, ensuring a predictable and traceable state management process.

Creating a Redux store involves defining an initial state and specifying how it can be modified. The state should be treated as immutable, meaning that it should not be modified directly. Instead, any changes to the state are made by dispatching actions.

Actions in Redux

Actions are payloads of information that send data from your application to the Redux store. They are the only source of information for the store and must have a ‘type’ property indicating the type of action being performed. Actions can also carry additional data, known as the ‘payload,’ which contains information about the action being executed.

Defining actions in Redux involves creating action creators, which are functions that return action objects. These action objects are then dispatched to the store using the dispatch function. By dispatching actions, developers initiate state changes within the store.

For example, you have a simple counter application. You might define an action type like this:

// Action Type
const INCREMENT = 'INCREMENT';// Action Creator
const incrementCounter = () => ({
type: INCREMENT,
payload: null // Payload can be any additional data
});// Dispatching the Action
store.dispatch(incrementCounter());

In this example, calling incrementCounter() returns an action object with the type ‘INCREMENT’. When this action is dispatched, it informs the Redux store to update its state based on the specified action type.

Reducers in Redux

Reducers are pure functions that specify how the application’s state changes in response to an action. A reducer takes the current state and an action as arguments and returns a new state based on the action type. It is essential to note that reducers should not modify the existing state but rather create a new state object.

Let’s extend the counter example to include a reducer:

// Reducer
const counterReducer = (state = { count: 0 }, action) => {
switch (action.type) {
case INCREMENT:
return { count: state.count + 1 };
default:
return state;
}
};

// Creating the Redux Store with the Reducer
const store = createStore(counterReducer);

In this example, counterReducer is a pure function that takes the current state and an action. If the action type is 'INCREMENT', it returns a new state object with the count incremented by 1. If the action type does not match any cases, it returns the current state unchanged.

The Redux Workflow

Understanding the Redux workflow involves recognizing the flow of actions through the system and how reducers respond to those actions.

  • Action Dispatch: Developers initiate state changes by dispatching actions using action creators.
  • Reducer Execution: Reducers specify how the state should change based on the action type.
  • New State Creation: Reducers create a new state object without modifying the existing state.
  • Store Update: The store receives the new state and updates its internal state accordingly.
  • View Re-render: Connected components re-render based on the updated state.
Image from dhwise.com

By following this workflow, Redux provides a predictable and traceable pattern for state management in complex applications.

Middleware in Redux

Middleware in Redux allows developers to extend the store’s abilities by intercepting and augmenting actions as they are dispatched. It provides a way to add additional functionality to the Redux workflow. Common use cases for middleware include logging, asynchronous operations, and handling side effects.

For example, the redux-thunk middleware enables the use of asynchronous actions in Redux. It allows action creators to return functions instead of plain action objects, enabling the dispatch of multiple actions over time.

// Using redux-thunk middleware for asynchronous actions
const fetchData = () => {
return (dispatch) => {
dispatch({ type: 'FETCH_DATA_REQUEST' });

// Simulating an asynchronous API call
setTimeout(() => {
dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });
}, 1000);
};
};

In this example, fetchData returns a function instead of a plain action object, allowing asynchronous operations before dispatching the actual actions.

Conclusion

Understanding the fundamentals of Redux — State, Actions, and Reducers — lays the groundwork for effective state management in your applications. By adopting a centralized store, predictable actions, and pure reducers, developers can maintain a clear and maintainable architecture. Additionally, the use of middleware extends Redux’s capabilities, enabling the handling of asynchronous operations and other side effects.

--

--