
State Machines in React: When Booleans Start Lying to You
isLoading, isError, isSuccess, isEditing — five booleans give you thirty-two combinations, and most of them are impossible states your code still has to survive. A state machine makes the impossible ones unrepresentable. Here's when to hand-roll one and when to reach for XState.
Read full article →
Undo/Redo Without Losing Your Mind: The Command Pattern in React
The instinct is to snapshot your whole state on every change and step backward through the copies. It works until it doesn't. A history of reversible commands scales further, describes what actually changed, and survives contact with a server. Here's how I build undo/redo that doesn't fall apart.
Read full article →
Optimistic UI: Updating Before the Server Says Yes
Optimistic UI is a small lie: you show the result before the server confirms it. Done right, the app feels instant. Done wrong, the UI quietly tells the user something that never happened. The difference is entirely in how you roll back.
Read full article →
Server State Is a Cache: Normalization, Duplicates, and Invalidation You Can Trust
The same customer shows up in a list, a detail page, and a header badge — three copies of one truth you don't own. Edit one and the others go stale. Here's when to normalize server data into one source of truth, when the query cache is enough, and how to invalidate without nuking everything.
Read full article →
localStorage Is Not State: Persistence, Hydration, and Tabs That Fight Each Other
localStorage looks like a global variable that survives a refresh. That framing is the bug. Treat it as a persistence layer that mirrors your state — not as the state itself — and the hydration mismatches, stale tabs, and schema breakages mostly disappear.
Read full article →
Keeping a UI Kit Updated Across Apps: Versioning, Contracts, and Trust
A shared UI kit does not fail because the button component is hard to write. It fails when five applications are afraid to upgrade it. Versioning, contract tests, release channels, and migration paths are what turn a component library from a dependency into a product people can trust.
Read full article →
Changing a Component Everyone Uses: Deprecation, Codemods, and No Big-Bang Rewrites
Writing the new version of a shared component is the easy 10%. The other 90% is the hundred call sites that already depend on the old one — and the fear of touching them. Here's how I change a component everyone uses without a month-long rewrite that breaks the day it lands.
Read full article →
Headless Components: Give Away the Behavior, Keep None of the Markup
The most reusable UI code I write renders nothing at all. Headless components, render props, and hooks-as-API are three names for one idea: separate what a component does from how it looks — and hand over the behavior without a single opinion about the markup.
Read full article →
Compound Components: Designing an API, Not Just a Component
The moment a component grows past a handful of props, you're not writing a component anymore — you're designing an API. Compound components are how you keep that API flexible without drowning it in configuration props.
Read full article →
Is Container vs Presentational Dead? What Survived the Hooks Era
The pattern that taught a generation to split 'smart' from 'dumb' components got quietly declared obsolete when hooks arrived. It wasn't. The folder convention died. The idea underneath it is more useful now than ever — including in Server Components.
Read full article →