State Management in React

State Management in React

State management is a crucial part of React applications. Choosing the right solution depends on the complexity and scalability of your project.

Why Do You Need State Management?

  • Efficiently share state across multiple components.
  • Avoid prop drilling, making the component tree cleaner.
  • Improve maintainability in large applications.

Context API: A Simple Solution

React’s built-in Context API is a lightweight way to manage global state without third-party libraries.

How to Use Context API

Create a Context:

import { createContext } from 'react';

const ThemeContext = createContext('light');

Provide the Context:

import { ThemeContext } from './ThemeContext';

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <ChildComponent />
    </ThemeContext.Provider>
  );
}

Consume the Context:

import { useContext } from 'react';
import { ThemeContext } from './ThemeContext';

function ChildComponent() {
  const theme = useContext(ThemeContext);
  return <p>Current theme: {theme}</p>;
}

When to Use Context API

  • Small to medium-sized applications.
  • Simple state sharing without complex updates.
  • Avoiding unnecessary re-renders using memoization techniques.

Redux: A Scalable Solution

Redux is a powerful state management library that provides a centralized store with predictable updates through reducers and actions.

How to Use Redux

Install Redux Toolkit:

npm install @reduxjs/toolkit react-redux

Create a Redux Slice:

import { createSlice } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: 'counter',
  initialState: { count: 0 },
  reducers: {
    increment: (state) => { state.count += 1; },
    decrement: (state) => { state.count -= 1; }
  }
});

export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;

Set Up the Store:

import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';

const store = configureStore({ reducer: { counter: counterReducer } });
export default store;

Provide the Store:

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

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

Use Redux in Components:

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

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

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => dispatch(increment())}>+</button>
      <button onClick={() => dispatch(decrement())}>-</button>
    </div>
  );
}

When to Use Redux

  • Large-scale applications with complex state logic.
  • Need for predictable state management and debugging tools.
  • Multiple components requiring shared and frequently updated state.

Context API vs Redux: Key Differences

Feature Context API Redux
Complexity Simple, built-in More complex, requires setup
Performance Can cause re-renders Optimized with reducers
Best For Small/medium apps Large-scale apps
Learning Curve Easier to learn Steeper learning curve