componentEngineering

React Fundamentals

Components, the hooks rules, the render model, and the traps that cause most React bugs.

1 item

Links1

01NotesNote

The mental model

A component is a function of its props and state that returns UI. React re-renders when state or props change, diffs the result against the previous render, and applies the minimal DOM changes. "Re-render" means React calls your function again — it does not mean the DOM was touched. Most performance confusion comes from conflating the two.

Hooks — the rules that actually matter

  • Only call hooks at the top level of a component or another hook — never in conditions, loops, or after an early return. React tracks hooks by call order.
  • useState — local state; setter triggers a re-render. Updates are batched, and state is a snapshot per render (count inside a closure is the value at render time, not "live").
  • useEffect — for synchronizing with external systems (subscriptions, DOM, network), not for deriving data. If you can compute it during render, don't put it in an effect.
  • The dependency array must list every value from the render scope the effect uses. Lying to it causes stale closures. Let the exhaustive-deps lint rule guide you.
  • useRef — a mutable box that survives renders without triggering one. For DOM nodes and "I need to remember something but not re-render."

Common traps

  • Derived state in state. If a value can be computed from props/state, compute it during render — don't mirror it into useState and sync with an effect.
  • Missing key in lists, or using array index as key when the list reorders — causes subtle state-bleed bugs. Use a stable unique id.
  • New object/array/function each render passed as a prop defeats memoization. Stabilize with useMemo/useCallback only when it matters.
  • Effects that should be event handlers. Reacting to a user action? That's an event handler, not an effect.

Composition over configuration

  • Prefer passing children and small focused components over giant prop-driven mega-components.
  • Lift state only as high as it needs to go — co-locate it with the closest common ancestor that needs it, no higher.