Skip to main content

State Management in React

This file covers different approaches to managing state in React applications.

Local State (useState)​

For simple, component-specific state:

import React, { useState } from 'react';

const Counter = () => {
const [count, setCount] = useState(0);

return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
};

Context API​

For sharing state across components:

import React, { createContext, useContext, useReducer } from 'react';

const AuthContext = createContext();

const authReducer = (state, action) => {
switch (action.type) {
case 'LOGIN':
return { ...state, user: action.payload, isAuthenticated: true };
case 'LOGOUT':
return { ...state, user: null, isAuthenticated: false };
default:
return state;
}
};

export const AuthProvider = ({ children }) => {
const [state, dispatch] = useReducer(authReducer, {
user: null,
isAuthenticated: false
});

return (
<AuthContext.Provider value={{ state, dispatch }}>
{children}
</AuthContext.Provider>
);
};

export const useAuth = () => useContext(AuthContext);

Redux Toolkit (Complex State)​

For large applications with complex state:

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

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

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

State Management Guidelines​

  • Start with local state
  • Use Context for medium complexity
  • Consider Redux for complex applications
  • Keep state as flat as possible
  • Normalize complex data structures
  • Use selectors to compute derived state