Chapter 2: Modern Frontend Development with React
This is Part 3 of the Modern Frontend Development series. There used to be one place called 'state' where everything went: API responses, modals, form drafts, theme, all sharing the same store. Once server state and client state emerged as separate concepts, the tools and patterns on each side became much clearer.
You'll see how server state and client state get handled in real-world scenarios, alongside popular libraries like TanStack Query and Zustand. The point is to help you pick the right library for each case and understand why, based on the actual characteristics of server vs client state, not on habit or tech hype.
Prerequisites
Server vs Client State
Tutorial Content
6 sections • about 75 minutes
Rewind a few years. If you asked a React developer where state lived, the answer fit on one line: in a useState here, lifted to a parent there, and for anything bigger, a store. Redux, MobX, flavor of the month, whatever you reached for, the job was the same: hold the bits the UI needs, let components subscribe.
Back then I was a huge Redux fan. Learning it in my early React days was tough: the dispatch-action-reducer flow, the immutability rules, the HOC boilerplate. When it finally clicked, though, it came with something that felt like magic. Open the DevTools, time-travel through the state, replay every action that had ever fired. If the store held everything, the DevTools saw everything. That kind of visibility is hard to walk away from.
At peak Redux hype, that pattern got pushed all the way. redux-form held your form state. Thunks dumped API responses into slices right next to it. Theme, modals, auth session, cached lists from the server, every bit of it got its own reducer. The store became the app, and whether a piece of state came from a remote API or a local click, it all lived under the same word: state.
one store, everything inside
Then the API work piled up. Every new endpoint meant the same routine: action type, action creator, FETCH_REQUEST / SUCCESS / FAILURE cases, a selector, a thunk or saga. Each one shipped the same loading / error / data triple a dozen others already had. Reaching for redux-saga to tame async only added more: generators, takeLatest, put, call, cancellation patterns. A whole second language, and two new endpoints still meant two new sagas plus slices that looked identical to the ones I wrote last sprint.
Caching was the part that never stopped hurting. Navigate away from the feed and back, and the slice refetched from scratch. Two components mount together, both dispatch the same fetch. Mutate an item on one screen, and a third reducer case is what kept the other screen in sync. Each of those was a problem I solved by hand, badly, in a different shape each time.
And because remote data and local flags shared one store, they bled into each other. A keystroke in redux-form could re-render a list backed by API data across the app. Without reselect and memoization everywhere, it stuttered.
At some point I started wondering what the app would look like if all that server-side pain lived somewhere else entirely. Imagine a separate layer that owned the cache, the deduping, the background refetch, the stale-then-fresh behavior, and the invalidation. With that handled, what's left in my store is the easy stuff: a theme, a modal flag, a sidebar toggle. Local, synchronous, small.
imagined: two sides of state
That's the split the community eventually drew, and the rest of this chapter lives on both sides of it. The next section names the two halves. The one with all the mess I just described is where we start digging in.
Share this tutorial
About the author
NAB, Lead Engineer
I'm Vu, a Lead Engineer at NAB (National Australia Bank). I started on Home Lending products and now lead a team building for HICAPS, Australia's largest point of sale claiming service for private health insurance. Before NAB, I worked at startups and across a range of teams and stacks.
Upskills is where I share practical, real-world knowledge to help you build and ship projects better. Beyond tutorials, more content is coming: project showcases, interview prep, and AI tools as resources for your learning journey. I'm excited to share what I've learned and keep learning together as we build cool things.
Practical web development deep-dives, every other week, written by an engineer who ships them. No fluff, no hot takes.
We respect your privacy. Unsubscribe anytime.