React Forum
Blog & Guide Responses
Feb 16, 2023 · 04:00 AM

Sharing state between components - discussion (2023-02-16)

Started by Theo Bennett
externalstatesharinglifting stateroute docsvaultsderived outputsevidencecontracts

The sharing-state page is the canonical "lift state up" story, but the real-world tension is: when does "lift to a parent" stop working and when do you need a route document or vault because there isn't a single natural parent (list + detail + overlay)? In the React Tips-ish posture, I like treating shared state as a contract: one place for truth, plus evidence so you can tell when panels disagree.

Read the page

When you share state across panels, do you still lift to a component parent, or do you use a route doc/vault? What shared outputs do you store as derived (counts, selection summaries) to keep UI consistent? How do you prevent shared state from becoming a global junk drawer?

Comments (14)

Back to latest
Marisol Vega
Feb 19, 2023 · 04:04 AM

We still lift to a parent when it’s truly local.

But the moment the state must survive route motion or be replayable with back/forward, it stops being "just a parent" and becomes a document.

Dmitri Kline
Feb 21, 2023 · 04:04 AM

We log shared-state transitions so "why did selection change" isn't a detective story:

txt
[tips] sharedState=selection set=doc_19 reason=list:click
[tips] sharedState=selection set=null reason=overlay:close
[tips] sharedState=filter set=status:open reason=tab:click

And we render a compact evidence summary: selection=doc_19 filter=status:open panel=detail.

Keira Santos
Mar 01, 2023 · 03:03 AM

Counterpoint: route docs and vaults are easy to abuse. Everything becomes shared state because it's convenient.

We require one of three reasons before sharing: navigation replay, cross-panel coherence, or persistence across remount boundaries.

Theo Bennett
Mar 05, 2023 · 05:05 AM

That's the right gating question: what user behavior requires this to be shared?

If the answer is "it was easier", it probably shouldn't be shared at all.

Grace McCoy
Mar 18, 2023 · 06:18 PM

Stored-derived shared outputs were the biggest coherence win: selection summary, counts, and current posture string.

Without those, each panel re-derives and you get subtle mismatches that feel like data corruption.

Jasper Nguyen
Apr 06, 2023 · 06:06 AM

Long-form: shared state is less about sharing variables and more about sharing *meaning*. If two panels need to agree on what "selected" means, you need a single surface where selection identity lives and a single vocabulary for selection changes.

The fastest way to make shared state go wrong is to share raw inputs but not share derived meaning (summary, lane, source). That's when panel A thinks selection is a draft and panel B thinks it's committed, and nobody can explain the UI.

Nina Kapoor
May 10, 2023 · 10:10 AM

We prevented junk-drawer stores by splitting into small domain docs: selection doc, filter doc, composer doc.

Each doc has a minimal schema and evidence keys. If a value doesn't belong in one of them, it probably shouldn't be shared.

Owen Price
Jun 01, 2023 · 06:06 AM

Counterpoint: lifting to a parent is still underrated. It's explicit and local and doesn't require governance.

I reach for docs/vaults only when there truly isn't a parent component that represents the shared surface.

Benji Rios
Jul 14, 2023 · 02:14 PM

Long-form counterpoint: shared state becomes dangerous when writes can come from multiple places without a merge rule. We introduced a merge policy (newer wins, but conflicts are logged) and it changed everything:

txt
[tips] sharedState conflict key=selection winner=panel:list loser=panel:overlay reason=newerWrite

Silent conflicts are where bugs go to live.

Lina Ortega
Aug 19, 2023 · 07:19 PM

Docs tie-in: the state and patterns docs are a good companion for contract-driven shared state.

Related: State Management (Best Practices) and Patterns Library.

Amina Farouk
Sep 18, 2023 · 12:12 PM

We treated drafts as multi-truth and committed on boundaries (blur/submit).

Sharing drafts globally made typing slower and made it impossible to reason about what the user actually committed.

Evan Brooks
Nov 12, 2023 · 04:04 AM

We render evidence in a visually-hidden contract line so tests can query it by text.

That kept us from coupling tests to attribute selectors while still making shared state visible.

Harper Iqbal
Dec 02, 2023 · 02:02 AM

A small governance trick: every shared doc has an owner and an intended audience (UI vs routing vs support).

If a key doesn't have an audience, it doesn't get added.

Rowan Pierce
Dec 20, 2023 · 06:18 PM

We also treat shared outputs as part of the product contract (counts, selection summary).

If those are derived in multiple places, the product will look inconsistent even if raw data is correct.

Salma Qureshi
Dec 31, 2023 · 09:09 AM

If you want shared state to be healthy: define the contract, define the merge rule, render evidence.

The page's "one source of truth" idea is still right; the real work is choosing what the truth is and how it's observed.