Concept
This is the capstone comparison for both the state-management and redux domains, Zustand, Jotai, MobX, and this entire redux domain each confirmed their own selective-re-rendering mechanism independently. This topic places all four side by side, mechanism by mechanism, using only claims already confirmed in their respective topics.
The four confirmed mechanisms, side by side
// REDUX: reducer reference-stability + useSelector reference-equality
const count = useSelector((state) => state.counter.value);
// CONFIRMED (Actions & Reducers): an untouched slice's reducer returns
// the EXACT SAME reference, useSelector's comparison then skips re-render
// ZUSTAND: selector + reference-equality on an EXTERNAL store (no React Context)
const count = useStore((s) => s.count);
// CONFIRMED (Zustand topic): a component subscribed via one selector
// is NOT notified when an unrelated slice changes elsewhere in the store
// JOTAI: per-ATOM subscription, no manual selector needed at all
const [count] = useAtom(countAtom);
// CONFIRMED (Jotai topic): each atom is its OWN independent subscription
// unit, a component using countAtom is never touched by changes to
// a completely separate atom, with no selector function required
// MOBX: Proxy-based AUTOMATIC dependency tracking
const Counter = observer(() => <span>{store.count}</span>);
// CONFIRMED (MobX topic): merely READING store.count during render
// automatically registers it as a tracked dependency, no selector,
// no atom declaration, tracking happens implicitly via Proxy interceptionstore.dispatch({ type: 'counter/incremented' });
dispatch() sends the action to the store's single root reducer, this is the ONLY way state changes in Redux; nothing else can mutate the store.
Every one of these four achieves the same practical outcome, a component doesn't re-render when unrelated state changes, through structurally different means: Redux requires an explicit reducer and an explicit selector; Zustand requires an explicit selector but no reducer/dispatch ceremony; Jotai requires neither a selector nor a reducer, just atom composition; MobX requires none of the above, tracking is fully automatic via Proxy interception of property reads.
Confirmed: the SAME underlying lesson, shown three different ways in AtomicStateVisualizer
const useStore = create((set) => ({count: 0,user: { name: 'Ada' },incrementCount: () => set((s) => ({ count: s.count + 1 })),renameUser: (name) => set({ user: { name } }),}));
Two components, each subscribed to a DIFFERENT slice of the same store via an explicit selector function. Neither has rendered yet in this walkthrough.
The AtomicStateVisualizer presets built for Zustand, Jotai, and MobX each demonstrated this same "which components actually re-render" question, confirmed against each library's real, installed package, and this domain's own ReduxFlowVisualizer demonstrated Redux's reducer-and-selector version of the identical question. The visual language is intentionally consistent across all four topics specifically because the underlying question, "does an update to one piece of state affect an unrelated component?", is the same question, answered differently by each library's architecture.
The genuinely decidable tradeoffs, not "which is objectively best"
| Redux (RTK) | Zustand | Jotai | MobX | |
|---|---|---|---|---|
| Update mechanism | dispatch + reducer (traceable action log) | Direct set() call | Atom set function | Direct property mutation (Proxy-intercepted) |
| Re-render granularity | Explicit selector | Explicit selector | Automatic, per-atom | Automatic, Proxy-tracked |
None of these rows has a universally "correct" value, a large team needing strict traceability and time-travel debugging for compliance/audit reasons has a genuinely different optimal answer than a small team building a prototype where boilerplate reduction matters more than an action log.