Mirror / Mirrored state

The problem

Query-string state usually starts with a hook that owns a parameter, and the usual things go wrong:

  • the URL becomes a second store, so the Model and the address bar disagree;
  • every parameter re-implements a codec, a default, and a history policy;
  • back and forward loop through a change handler that writes what it just read;
  • a preference lives in localStorage reads scattered through views;
  • two tabs, or an old link, restore a value over an edit the user just made.

The fix is to keep the Model authoritative and derive the mirror: one writable projection names the slice, the store is written when the slice changes, and navigation or a cold load reduces the store back into the Model through update.