React Forum
Blog & Guide Responses
Oct 04, 2022 · 04:00 PM

[Deep Dive #26] Mutable Object Beacons - discussion

Started by Soren Malik
blogstatebeaconsmutable objectsvaultmirrors

We have a couple hot routes where “the store write on every render” tax is real, and people are reaching for globals again — but I want it to be predictable, not random.

Read the post

What do you consider a legitimate beacon (fast truth / render evidence) vs a global that’s just avoiding ownership? How do you reconcile beacon drift on purpose (mirrors + effects) without turning it into an effect maze? Do you render beacon evidence (counters/flags) in the route surface so the story is explainable from a screenshot?

Comments (10)

Back to latest
Maya Henson
Oct 04, 2022 · 04:05 PM

If you can’t name the beacon and explain why it’s fast truth, it’s not a beacon. It’s just a global variable with better marketing.

Dmitri Kline
Oct 04, 2022 · 04:14 PM

The post’s framing (fast truth vs durable truth) is useful.

We only allow beacons for hot counters / route posture evidence, and we always mirror into a durable store eventually.

Related: State Management Best Practices and Vault Confluence (Deep Dive #23).

Amina Farouk
Oct 04, 2022 · 04:26 PM

We render the beacon evidence so you can tell what’s happening without devtools:

tsx
export const beacons = { renders: 0, warmed: false, route: '' };

export function RouteShell() {
  beacons.renders += 1;
  beacons.route = '/dash';
  return <div data-beacon={beacons.route} data-renders={beacons.renders} data-warmed={String(beacons.warmed)} />;
}
Hana Saito
Oct 04, 2022 · 04:35 PM

Counterpoint: global mutable objects get scary once multiple tabs exist.

If you’re not pairing it with tab sync + a mirror ledger, you’ll debug “why is this tab different” forever.

Soren Malik
Oct 04, 2022 · 04:40 PM

Yep. In our app the beacon is explicitly “per tab” and the durable vault is “shared reality”.

The mismatch is acceptable only if it’s visible and reconciled on cadence.

Hana Saito
Oct 04, 2022 · 04:43 PM

That framing helps: drift is allowed, but only as evidence, not as an accident.

Priya Liao
Oct 04, 2022 · 04:51 PM

We had success using beacons for “is warmed” and “last selected id” but never for user-visible data.

If users can see it, it belongs in durable truth, not in a mutable object.

Noah Vance
Oct 04, 2022 · 04:59 PM

The scary part is reconciliation effects that quietly rewrite durable truth based on a beacon.

I want a strict rule for when beacon wins vs when vault wins.

Salma Qureshi
Oct 04, 2022 · 05:11 PM

We made the “beacon -> vault” reconciliation explicit and evented:

tsx
function useBeaconReconcile(appVault: any) {
  useRenderEffect(() => {
    appVault.write('metrics.beaconRenders', beacons.renders);
    appVault.write('route.active', beacons.route);
  });
}

If it’s not written in one place, it ends up scattered across the tree.

Camille Duarte
Oct 04, 2022 · 05:23 PM

The best part of the post is calling hot counters “render evidence”.

That wording makes it harder for people to smuggle product state into beacons.

Inez Park
Oct 04, 2022 · 05:36 PM

If you don’t render the beacons, you’ll still use them — you just won’t know you’re depending on them.

Benji Rios
Oct 04, 2022 · 05:49 PM

My guardrail: beacon keys must be enumerated and owned.

If someone adds beacons.foo = ... in a random component, that’s a contract violation.