top

Search

Software Key Tutorial

.

UpGrad

Software Key Tutorial

Redux in React

Introduction

React is a popular JavaScript library for building user interfaces. It excels at managing the state locally within components. However, as your app grows larger, managing state across multiple components can become challenging. This is where Redux comes in, especially when considering Redux in React. Redux is a predictable state management library that helps manage the state across your entire application.  This Redux tutorial will explain what is Redux and why is it useful. We will also discuss the React Redux maintained by the Redux team.

By the end of this Redux tutorial, you will have a solid understanding of what is Redux in React and how to use it effectively in your React apps.

Overview

Redux is an open-source JavaScript library created by Dan Abramov and Andrew Clark. It was inspired by Facebook's Flux architecture and provides a single source of truth for the application state.

Redux aims to make state management predictable by imposing certain restrictions on how and when updates can happen. These restrictions allow you to trace when, where, why, and how your application's state changed. Redux helps you manage the state across your entire app with ease. Let’s start with the Redux tutorial and explore Redux in detail.

What is Redux?

Redux is a predictable state container for JavaScript applications. It helps you write applications that behave consistently across client, server, and native environments and are easy to test.

Redux revolves around a strict unidirectional data flow and central data store. This makes tracking changes and debugging easier.

The main concepts and components of Redux are:

  • Store - Store is the single source of truth for the application state. It holds the entire app state in a tree structure.

  • Actions - Plain objects describing intent to change state. For example, LOGIN_USER.

  • Reducers - Pure functions taking state and actions as input and returning a new state. State mutations occur in reducers.

  • Store methods - getState(), dispatch(action), and subscribe(listener) are the methods to interact with the store.

The Redux store calls the root reducer whenever an action is dispatched. The root reducer may combine the output of multiple reducers into a single state tree.

Why Redux?

As React applications grow in scale, managing state across components can get difficult. Some of the problems faced are:

  • Components that need the same state are located far apart in the component tree. Passing props down multiple levels is cumbersome.

  • Certain components need access to multiple pieces of state. We end up passing a complex tangle of props around components.

  • Shared state logic often gets duplicated across components when it needs to be updated.

Redux State Management

Without Redux, components that need the same data have to pass props down through multiple levels.

Redux solves this problem in the following ways:

  • Providing a central store that holds the application state. Any component can access the state it needs directly from the store.

  • State mutations happen through dispatched actions only. This makes tracking state changes predictable.

  • The reducers that mutate state are pure functions without side effects. This makes debugging easier.

Overall, Redux makes state management scalable by lifting shared state out of React components into a global store. Components can access the state they need without prop drilling.

Why Use React Redux?

While Redux can be used with any UI framework, it is most commonly used with React. Here are some of the benefits of using React Redux together:

  • Seamless integration - React Redux integrates Redux with React apps smoothly with the <Provider> and connect() APIs.

  • Preserves React principles - React Redux allows you to follow React principles like unidirectional data flow and separation of concerns.

  • Efficient updates - It enhances the performance of React applications by avoiding re-rendering.

  • Developer tools - React Redux was inspired by Redux DevTools. It comes with built-in functionality for debugging through time travel.

  • Ease of use - The APIs of React Redux are user-friendly and straightforward for developers experienced in React.

  • Large ecosystem - React Redux benefits from a community that provides documentation and a wide range of third-party libraries.

To put it simply, React Redux brings together the strengths of Redux, React and Redux DevTools to provide a way of managing state in React applications.

Principles of Redux

Redux follows three key principles that make application state management predictable, especially when considering redux in react native:

1. Single source of truth

The entire state of your app is stored in a single store. This makes it easy to track changes. The single state tree makes debugging easy as there are no multiple versions of the state spread across components.

2. State is read-only

The only way to change the state is by dispatching actions. Actions describe the intent to change state. Since actions are the only way to describe changes, debugging is easier.

3. Changes via pure functions

State changes happen through reducer functions. Reducers are pure functions. They take the previous state and return the next state. The output depends only on the input arguments.

Since reducers are pure functions without side effects, you can replay the actions and get the same state output every time. This makes debugging predictable.

Redux Architecture

Redux follows a unidirectional data flow model:

  1. A component dispatches an action when the user interacts with it. For example, clicking a Login button can trigger a LOGIN_REQUEST action.

  2. The Redux store calls the reducer function with the previous state and action as arguments. The reducer returns the next state.

  3. The store saves the complete state tree returned by the reducer. All subscribers are notified of the update.

  4. The component receives the updated state via props and re-renders with new data.

This pattern continues whenever the subsequent action is sent out. The action explains "what occurred" in your application while the reducer manages how the state is modified.

Redux Installation

Let's examine the steps involved in installing Redux and integrating it into a React application.

1. Create a React App

To begin, we can initiate a React project by utilizing the Create React App tool.

npx create-react-app my-app
cd my-app

2. Install Redux and React Redux

Next, we can proceed with installing the packages for Redux and React Redux from NPM.

npm install redux react-redux

3. Create Store

Next, we move forward with the creation of a file named src/store.js in order to establish and customize our Redux store.

import { createStore } from 'redux';

const store = createStore(() => {}); // reducer function

export default store;

4. Set up Provider

We have to enclose the <App> component within the <Provider> in index.js. This enables components to establish a connection with the store.

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

This feature enables all elements within the application to connect to the Redux store using the React Redux connect() API.

That's everything you need to do! Our React application is now linked with Redux. Moving forward, we will delve into examples to demonstrate how Redux functions in real-world scenarios.

Pros and Cons of Redux

Following are some of the key pros and cons of using Redux:

Pros

  • Centralized app state makes debugging easy

  • Writing predictable code by enforcing restrictions on when/how states can change

  • Ease of tracing changes - Redux DevTools provides powerful debugging capabilities like time travel

  • Works well with immutable data structures, which avoid mutation issues

  • The ability to persist state-to-local storage allows for offline access

  • Large ecosystem of ad-ons like middleware, DevTools, React bindings etc.

Cons

  • More code for you to write - actions, reducers, constants

  • More concepts for developers to learn - actions, reducers, store, middleware

  • Overkill for small projects - more useful when managing complex state

  • Boilerplate code for setup/installation. However, starter kits can help.

  • Overall, Redux works very well for medium and large-scale apps. The benefits outweigh the extra code you have to write once the app's complexity grows.

Demo Application: React with Redux

1. Setup

npx create-react-app redux-counter-demo
cd redux-counter-demo

2. Install Required Packages

npm install redux react-redux

File Structure:

redux-counter-demo/
├── src/
│   ├── redux/
│   │   ├── actions.js       # Action creators
│   │   ├── reducers.js      # Reducer function(s)
│   │   └── store.js         # Redux store
│   ├── App.js               # Main React component
│   └── index.js             # Entry point
└── package.json

3. Redux Implementation:

actions.js:

export const increment = () => ({ type: 'INCREMENT' });
export const decrement = () => ({ type: 'DECREMENT' });

reducers.js:

const initialState = {
  count: 0
};

function counterReducer(state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + 1 };
    case 'DECREMENT':
      return { ...state, count: state.count - 1 };
    default:
      return state;
  }
}

export default counterReducer;

store.js:

import { createStore } from 'redux';
import counterReducer from './reducers';

const store = createStore(counterReducer);

export default store;

React Components:

App.js:

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from './redux/actions';

function App() {
  const count = useSelector(state => state.count);
  const dispatch = useDispatch();

  return (
    <div className="App">
      <h1>Redux Counter Demo</h1>
      <p>Count: {count}</p>
      <button onClick={() => dispatch(increment())}>Increment</button>
      <button onClick={() => dispatch(decrement())}>Decrement</button>
    </div>
  );
}

export default App;

index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Provider } from 'react-redux';
import store from './redux/store';

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

4. To run the application:

npm start

Output:

Conclusion

Whether you are just starting out with Redux or brushing up on core concepts, this tutorial provides a helpful overview. Redux is a very useful tool to have in your web development toolkit, especially when building data-intensive applications with React.

Some key takeaways from this react redux tutorial are:

  • Redux provides predictable state management - State mutations happen in a strict order and follow unidirectional data flow. This makes tracking changes and debugging easier.

  • Core concepts are store, actions, reducers - The store is the single source of truth. Actions describe intent to change state, and reducers mutate the state.

  • React Redux connects React apps to Redux - React Redux provides intuitive APIs like <Provider> and connect() to integrate Redux with React apps.

  • Redux works best for complex applications - While Redux requires more code, it pays off when managing state across larger apps with data shared across components.

  • Redux enables powerful capabilities like undo/redo, persistence, and time travel debugging.

FAQs

1. What is the difference between React context API and Redux?

The React context API provides an easier way to pass data down the component tree without prop drilling. However, it is more limited compared to Redux which offers capabilities like store subscriptions, middleware, time travel debugging etc. Context is useful for simple cases while Redux excels at complex state management.

2. How does Redux work with server-side rendering?

On the server, you create a store instance and preload it with state. The client creates a store using the same reducer and initial state. React Redux can setup synchronization between the stores.

3. What is the suitability of Redux for small apps?

Redux does require more code. For small apps where state is managed locally, Redux may be overkill. As your app grows, Redux helps avoid prop drilling and provides centralized state.

4. How does Redux compare to React's useReducer hook?

The useReducer hook allows using the reducer pattern locally in components. However, Redux provides additional capabilities like middleware, store subscriptions, and DevTools integration which useReducer does not.

Leave a Reply

Your email address will not be published. Required fields are marked *