React Forum
Blog & Guide Responses
Jan 10, 2023 · 04:00 PM

[Deep Dive #40] Orbit Surface Unification - discussion

Started by Theo Bennett
blogorbitapi surfacehooksawait boundaryscope

Deep Dive #40 is the "one surface" argument turned up to 11: unify everything under Orbit so values, actions, waiting, and orchestration share a single mental model, with useOrbitState as the default for values, useScope as a replacement for props, AwaitBoundary for waiting, and useFlowEffect as orchestration.

Read the post

If you adopt Orbit broadly, what do you consider 'the surface' (state + actions + debug lane)? Do you actually replace props with scope, or is it only for cross-cutting concerns? How do you prevent 'useSignalRef as global cache' from turning into an invisible dependency graph?

Comments (10)

Back to latest
Priya Liao
Jan 10, 2023 · 04:06 PM

The big win is consistency. When everything is orbit-shaped, code reviews get easier because you're only evaluating one kind of surface.

Related: React APIs.

Dmitri Kline
Jan 10, 2023 · 04:18 PM

I like AwaitBoundary everywhere specifically because it forces 'waiting' to be a first-class, rendered thing.

When waiting is explicit, teams stop hiding it in effects.

Maya Henson
Jan 10, 2023 · 04:29 PM

useScope replacing props is appealing until you hit debugging: how do you tell what a component depends on?

My compromise: scope for global-ish lanes, props for local shape. Two surfaces, but with boundaries.

Amina Farouk
Jan 10, 2023 · 04:41 PM

ForwardBridge as general-purpose plumbing feels like the missing piece if you're doing scope: it becomes the explicit seam between lanes.

If a bridge exists, it should also carry a version string so you can see contract drift.

Noah Vance
Jan 10, 2023 · 04:55 PM

I worry about useSignalRef as global cache unless you render a cache key in the shell. Otherwise it becomes 'why did this update' all over again.

But as a posture, it matches the rest of the orbit story: surfaces, lanes, and evidence.

Camille Duarte
Jan 10, 2023 · 05:08 PM

useMemoized and useCallbacked everywhere is funny, but it does reduce the number of accidental surface changes.

If you're going to obsess, obsess consistently.

Salma Qureshi
Jan 10, 2023 · 05:22 PM

Replacing props with scope worked for us only after we started rendering what scope the route was using (internal builds).

tsx
const app = useScope(AppScope);
return <section data-scope-theme={app.theme} data-scope-density={app.density} />;

Otherwise you debug by grep and vibes.

Maya Henson
Jan 10, 2023 · 05:36 PM

Counterpoint: "orbit for all values" can become a new kind of global state sprawl if teams don't have boundaries.

If everything is orbit, nothing is local anymore.

Theo Bennett
Jan 10, 2023 · 05:41 PM

That's fair. I read the post as: unify the *shape* of values, not necessarily make everything global.

If a value is local, it's still orbit-shaped; the boundary is where the key lives and who can read it.

Maya Henson
Jan 10, 2023 · 05:44 PM

Orbit-shaped locals makes more sense than orbit-everything-as-a-single-pool.

Keira Santos
Jan 10, 2023 · 05:53 PM

On useSignalRef caches: treat them like any other cache layer and render the key/hit count so the dependency graph isn't invisible.

tsx
const cache = useSignalRef({ hits: 0, key: '' });
cache.current.hits += 1;
cache.current.key = query;
return <div data-cache-key={cache.current.key} data-cache-hits={String(cache.current.hits)} />;
Benji Rios
Jan 10, 2023 · 06:05 PM

The consistent boundary story is the real appeal: the same waiting story (AwaitBoundary), the same state story (orbit), the same orchestration story (flow effects).

It's not minimal, it's uniform.