State Management in React

Local State vs Global State

Local State

Local state refers to data that is managed within a single component using the useState or useReducer hooks. It is ideal for temporary data such as form inputs, toggles, and UI visibility.


import { useState } from 'react';

function Toggle() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>
        {isOpen ? 'Hide' : 'Show'}
      </button>
      {isOpen && <p>This is toggled content.</p>}
    </div>
  );
}
  

Global State

Global state is data that needs to be accessible across multiple components or layers of the app, such as user authentication, theme preferences, or language settings. React does not include built-in global state management beyond the Context API. For more complex needs, external libraries like Redux or Zustand are used.

Context API

The Context API is React’s built-in solution for sharing state across the component tree without prop drilling.

Creating and Using Context


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

// 1. Create context
const ThemeContext = createContext();

// 2. Provide context value
function ThemeProvider({ children }) {
  const [darkMode, setDarkMode] = useState(false);
  const toggleTheme = () => setDarkMode(prev => !prev);

  return (
    <ThemeContext.Provider value={{ darkMode, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// 3. Consume context
function ThemeToggleButton() {
  const { darkMode, toggleTheme } = useContext(ThemeContext);

  return (
    <button onClick={toggleTheme}>
      Switch to {darkMode ? 'Light' : 'Dark'} Mode
    </button>
  );
}
  

Context is great for app-wide settings or simple shared state, but may become inefficient for large or rapidly changing data.

Introduction to Redux and Zustand

Redux

Redux is a popular and mature state management library that uses a centralized store, actions, and reducers to manage state. It’s useful for complex applications with deeply nested components or predictable state transitions.

Install Redux and React bindings:

npm install @reduxjs/toolkit react-redux

Example Redux store using Redux Toolkit:


// store.js
import { configureStore, createSlice } from '@reduxjs/toolkit';

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

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

export const store = configureStore({
  reducer: { counter: counterSlice.reducer }
});
  

Connect it to your app:


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

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

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

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

Zustand

Zustand is a minimal and intuitive state management library. It requires less boilerplate than Redux and works seamlessly with React.

Install Zustand:

npm install zustand

Create a global store:


import { create } from 'zustand';

const useStore = create(set => ({
  count: 0,
  increment: () => set(state => ({ count: state.count + 1 })),
  decrement: () => set(state => ({ count: state.count - 1 }))
}));
  

Use it in components:


function Counter() {
  const { count, increment, decrement } = useStore();

  return (
    <div>
      <button onClick={decrement}>-</button>
      <span>{count}</span>
      <button onClick={increment}>+</button>
    </div>
  );
}
  

Conclusion

State management is a core part of any React application. Use local state for simple, component-specific data, the Context API for shared app-wide state, and tools like Redux or Zustand for complex or scalable scenarios. In the next post, we’ll explore how to fetch data from APIs and manage server state efficiently in React.

Post a Comment

0 Comments