Server Components Rewired My Data Fetching
For three years, my React data fetching looked the same. Component mounts, useEffect fires, loading spinner renders, fetch resolves, state updates, component re-renders. Every page, every dashboard card, every list view followed this pattern. I wrapped it in custom hooks, abstracted it with SWR and React Query, but the mental model stayed fixed: the client asks, the server answers, the component reacts.
Server Components broke that model.
The New Model: Components Fetch Where They Live
Server Components let a component run on the server with direct access to your data layer, then send only the rendered HTML to the client. No useEffect. No loading state for initial data. No client-side JavaScript for data the server can fetch and render.
The mental model shifts from "fetch then render" to "render fetches."
Where This Wins
SEO-critical pages (product pages, blog posts). Data-heavy dashboards (each section is its own async component fetching in parallel). Reduced client bundle size (components that only display data ship zero JS).
Where Client-Side Fetching Still Wins
Interactive components (search with instant results, drag-and-drop). Real-time data (live transaction feed). User-driven fetch chains (fetch B depends on fetch A triggered by a click).
The Mental Model That Clicked
My transaction dashboard uses server components for the data-heavy sections and client components for the interactive parts. The server renders the full page with data. The client hydrates the interactive bits.
This is the same principle as progressive enhancement, applied at the component level. Render the content on the server. Add interactivity on the client.
$ /related
One CSS Grid Line Fixed Our Entire Dashboard Layout
Six media query breakpoints, five layout bugs, and one CSS Grid line later, our dashboard just worked. Why auto-fit beats fixed breakpoints.
React Server Components Made Me Rethink Client-Side
RSC doesn't just move rendering to the server. It destroys the 'client vs. server' mental model and replaces it with something sharper.
I Replaced Three useEffect Chains With One Zustand Store and Lost 200 Lines
Three dependent useEffect chains tangled across a dashboard component. One Zustand store with derived state fixed it. Here is how the refactor went.