Back to Blog
May 1, 2026
2 min readUpdated: May 12, 2026Handling State in Modern React Applications
Do you have a question or doubt about something?
Scroll down to the bottom to ask your question, and I or anyone else will respond!
Choose the right tool for the job. Here's how .
The Decision Matrix
| Scenario | Best Tool | Why |
|---|---|---|
| Local UI state (modal open/closed) | useState | Simple, built-in |
| Form state | useReducer + Context | Complex validation |
| Server cache (API data) | React Query / TanStack Query | Automatic refetching, caching |
| Global app state (user, theme) | Zustand or Context + useReducer | Lightweight, simple |
| Complex enterprise state | Redux Toolkit | Predictable, DevTools, large ecosystem |
| URL state (filters, pagination) | Next.js router / React Router | Source of truth in URL |
Implementation Examples
Zustand (recommended for most apps)
import { create } from 'zustand';
interface CounterState {
count: number;
loading: boolean;
increment: () => void;
decrement: () => void;
incrementByAmount: (amount: number) => void;
}
export const useCounterStore = create<CounterState>()((set) => ({
count: 0,
loading: false,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
incrementByAmount: (amount) => set((state) => ({ count: state.count + amount })),
}));
// Use in component
function Counter() {
const { count, increment, decrement } = useCounterStore();
// Only re-renders when 'count' changes due to selector
}
Redux Toolkit (for complex apps)
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 }
}
});
// Create typed hooks
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
Performance Rule
> "Atlassian removed their barrel files and saw a 75% reduction in average build times, a 30% improvement in IDE highlighting speed, and an 88% drop in unit tests executed per PR"
Key insight: How you organize your state management code affects your entire development experience.
Step-by-Step: Choose Your State Management
- Start with local state (
useState,useReducer) - Lift state up when 2+ components need it
- Add Context when 3+ levels deep
- Add Zustand/Redux when Context causes performance issues
- Add React Query when you have server data
Resources
| Library | Docs | When to Use |
|---|---|---|
| Zustand | docs.pmnd.rs/zustand | Most new apps |
| Redux Toolkit | redux-toolkit.js.org | Enterprise, existing Redux |
| Jotai | jotai.org | Atomic state |
| React Query | tanstack.com/query | Server state |
Was this helpful?
Discussion
0Do you have a question or any doubt?
Ask here and I or anyone else will respond!
Loading comments...
2B
By 2BigDev
Full-Stack Engineer