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