State Management in React: Context API and Introduction to Redux

Introduction to State Management

State management is a critical concept in React for:

  • Sharing data across components.
  • Keeping the UI in sync with the application state.

React provides two primary ways to manage state:

  1. Context API: For moderate state sharing across a component tree.
  2. Redux: For complex state management with predictable updates.

Context API

The Context API allows you to share state across the component tree without passing props down manually at every level.

2.1 When to Use Context API

  • Avoiding “prop drilling” (passing props down multiple levels).
  • Sharing global data like user authentication, themes, or language preferences.

2.2 Setting Up Context API

  1. Create a Context

import React, { createContext, useState } from 'react';

const UserContext = createContext();

export default UserContext;

Provide Context Wrap your app with the Provider component and pass the shared data.

import React, { useState } from 'react';
import UserContext from './UserContext';

function App() {
  const [user, setUser] = useState({ name: 'John', age: 30 });

  return (
    <UserContext.Provider value={{ user, setUser }}>
      <ChildComponent />
    </UserContext.Provider>
  );
}

export default App;

Consume Context Use the useContext hook to access the shared state in child components.

import React, { useContext } from 'react';
import UserContext from './UserContext';

function ChildComponent() {
  const { user, setUser } = useContext(UserContext);

  return (
    <div>
      <h1>{user.name}</h1>
      <button onClick={() => setUser({ ...user, age: user.age + 1 })}>
        Increment Age
      </button>
    </div>
  );
}

export default ChildComponent;

Advantages of Context API

  • Built into React (no additional library required).
  • Simplifies prop drilling.
  • Easy to set up for small to medium-scale applications.

Introduction to Redux

When to Use Redux

  • Large-scale applications with deeply nested components.
  • Sharing state across unrelated components.
  • Handling complex state logic or asynchronous updates.

 Core Concepts of Redux

  1. Store: The single source of truth for the application’s state.
  2. Actions: Plain JavaScript objects that describe what to do.
  3. Reducers: Pure functions that update the state based on actions.
  4. Dispatch: A method to send actions to the reducer.

 Setting Up Redux

Step 1: Install Redux

npm install redux react-redux

Step 2: Create a Redux Store

import { createStore } from 'redux';

// Initial State
const initialState = {
  count: 0,
};

// Reducer Function
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;
  }
}

// Create Store
const store = createStore(counterReducer);

export default store;

Step 3: Connect Redux to React

  1. Wrap your app with the Provider component.

import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import Counter from './Counter';

function App() {
  return (
    <Provider store={store}>
      <Counter />
    </Provider>
  );
}

export default App;

  • Use useSelector to access state and useDispatch to dispatch actions.

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';

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

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>
        Increment
      </button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>
        Decrement
      </button>
    </div>
  );
}

export default Counter;

Comparison: Context API vs. Redux

FeatureContext APIRedux
ComplexityLowHigh
Learning CurveEasySteeper
Ideal ForSimple to medium state sharingComplex and large-scale apps
Asynchronous HandlingNeeds custom implementationBuilt-in with middleware like redux-thunk

Best Practices for State Management

  1. Keep State Minimal: Only store what’s necessary.
  2. Structure State Carefully: Organize state logically for easier maintenance.
  3. Use Context Sparingly: For frequent updates, consider alternatives to avoid re-rendering.
  4. Combine Tools: Use Context API for themes and Redux for app-wide complex state.