Next.js App Router: A Practical Guide for Real Projects
Server components, layouts, loading states and caching explained with the decisions that matter when you ship a real Next.js site.
"Which state library should I use?" is the wrong first question. Ask what kind of state you have.
Open menus, form inputs and toggles belong in useState inside the component that owns them. Most state should stay here.
When a few components need the same value, lift it to their closest parent. If it must be reached from far apart, React Context works for low-frequency values such as the current theme or signed-in user.
Context re-renders every consumer when its value changes, so avoid putting fast-changing data in it.
Data that lives on a server, such as lists, profiles and orders, is not really your state. It is a cache of someone else's data. Use TanStack Query (or a similar tool) to fetch, cache, dedupe and refetch it, plus loading and error states for free.
const { data, isLoading } = useQuery({
queryKey: ['posts', page],
queryFn: () => api.get('/posts', { page }),
});
This removes most of what people used Redux for.
Filters, search text, sorting and pagination belong in the URL. Pages become shareable, and the back button works.
Use a form library such as React Hook Form with schema validation, instead of wiring many useState calls.
For genuinely global client-only state, like a shopping cart or editor settings, a small store such as Zustand is often enough. Reach for Redux Toolkit when you need strict structure, middleware or time-travel debugging across a large team.
useState.Classify the state first. Most apps need only local state, a data-fetching library and the URL.
Server components, layouts, loading states and caching explained with the decisions that matter when you ship a real Next.js site.
Stop guessing. Measure first, then apply the React optimizations that move the needle: memoization, code splitting, list rendering and more.
Typing props, hooks, events and API data with TypeScript, plus utility types and patterns that remove whole classes of bugs.