Stop overthinking UI state

Eliminate complexity and challenge the underlying assumptions of UI state

Exhibition Status

In progress

Gallery I: Foundations

Mental models of state

Intro

Think like an architect, not a replaceable coder. With the emergence of AI, you need to fundamentally shift how you operate. It's not enough to know syntax or the techne (the know-how). You need to understand the why deeply so you can make high-impact, high-leverage calls for your team and business.

Ⅰ. Inputs and outputs

UI state is often overcomplicated. It takes courage to reframe our thinking and start from zero.

When we step back and challenge how we think about and structure state in our frontend applications. At the heart of it, we just need to do two things:

  1. Take inputs - Save data
  2. Show outputs - Display fresh data
Inputs and outputs diagram

This is an obvious over-simplification, however let's just step back and look at the forest broadly and poke holes in our own mental models before layering on complexity with libraries. It is far too common for folks to reach for a state management solution (TM for spicy-ness).

What's the end result of this? Well… now you have at least two sources of truth:

  1. the database
  2. the state management library in the UI

And likely a 3rd…

  1. component state

Now your team is trying to piece together maps (sources of truth) while traversing the mist-filled trails. This leads to misunderstandings and mis-guided attempts to keep everything in sync across the outdated maps during development. The act of building software should never require you to perform forensics on how/where states converge.

Abstract map visualization

Instead I'd challenge you to hike with one map (source of truth) that you put together at the top of the mountain.

To develop this mental map, let’s drill down into the the different layers of state, deconstruct, challenge, and reframe our own understanding of UI "state".

Ⅱ. One source of truth

The only true source of truth lives in the database, and we should anchor our decisions from the fundamentals.

Let's think about data management in layers and on a spectrum of longevity:

  • server = truth (long-lived remote data). Note: this is not "state".

  • client state = transient (short-lived)

  • view = in memory state from form inputs/etc

The server stores the long-lived data. Client-side state is fundamentally transient.

We need to STOP treating remote data as if it were primary client state instead of something fetched and cached.

Don't recreate state
Many problems surface when we attempt to re-create remote data inside the UI. Prop-drilling and complex orchestration layers are symptoms of this illness.

Believe me when I say that I've been the victim of over-engineered frontend code which directly violated the principle of having one source of truth. Practically this often stems from the misguided attempt to manage remote data (outputs) in the same place as client state (inputs).

The worst offender I've laid eyes on was a case where HTTP requests were routed through a tangled mess of useReducer, redux and even React context somehow thrown in there to manage UI state for a..... simple form.

It was a complete disaster.

Stick to the fundamentals. Don't over-engineer.

Ice sculpture

Just like an ice-sculpture is crafted by removing material. We sharpen our mental models by removing unnecessary abstractions.

Ⅲ. Server data is NOT state

To organize data flow, we need a new lens.

Simply put, state changes over time. It's not the props passed in from a parent, nor derived from existing state or props in your app.[1]

I'd even argue that state is not data from your database. If it comes from your database, it's an output to display. That's a caching problem at the HTTP layer.

State should be thought of as synonymous with your inputs in your app. Not the outputs/database data. Keep these lanes separate! To be reductionist, the two lanes are:

  1. Inputs
  2. Outputs

Exhibition Status

Additional galleries under curation

Gallery II will cover managing inputs: form state, validation, and event handling patterns.

Gallery III will demonstrate displaying outputs: React Query integration, server caching strategies, and data fetching patterns.

Gallery IV presents a complete wizard case study tying everything together with URL state, multi-step forms, and database integration.