Skip to Content
All posts

Keeping state predictable in React: small habits that save hours

 — #react#javascript#frontend#patterns

I used to treat state like a second-class citizen: push it around, patch it in a hurry, and then wonder why bugs popped up days later. Over time I learned a few small habits that make state predictable and debugging less painful. These are the things I actually still do on real projects.

  1. Prefer explicit state shape over ad-hoc objects

Pick a clear shape and stick to it. If a component needs {loading, error, data}, keep that consistent across similar components. When shape is predictable, you can reason about transitions rather than individual fields.

  1. Co-locate the minimal state

Keep state as close as possible to where it's used. Derived values belong in selectors or computed values, not in the shared writable state. Move state up only when multiple children truly need it.

  1. Favor immutable updates (even in small apps)

Using shallow copies with spread or helper utilities prevents accidental mutations that leak through props. The mental overhead is small; the benefits compound when you revisit code later.

  1. Use local reducers for complex local logic

If a single component has several interacting flags, a small useReducer keeps transitions explicit and testable compared to juggling multiple useState calls.

  1. Keep side effects predictable

Prefer effects that are idempotent and derive from state changes. Isolate subscriptions and clean them up. When side effects are tangled with rendering, it's much harder to reason about the state machine.

  1. Prefer explicit events rather than implicit mutations

Name the intent (e.g., 'startFetch', 'fetchSuccess', 'fetchFailure') instead of hiding behavior inside setters. Event names read better in logs and tests.

  1. Add cheap tests for reducers and selectors

They don't need to be exhaustive — test the important happy and unhappy paths. Tests are the fastest way to catch regressions as your app grows.

Closing thought

Small, consistent habits add up. If you make state predictable, your future self will thank you when an afternoon of debugging becomes a 10‑minute fix. The real win is not a specific library or framework — it's a pattern of thinking about state transitions clearly.

— Mustaque