Building sections
Talking to other sections
Props, shared state, and when to use which.
Every island is its own createRoot, so React Context cannot reach between them.
There are three ways across, and which one you want depends on whether you need
props or state.
| Need | Use |
|---|---|
| Another section's Liquid data | useSectionProps(name) |
| Two sections agreeing on a value | useShared(key, initial) |
| A section exposing its own state | usePublish(key, value) |
| A designed domain — cart, overlays | createStore |
Props are already public
Every section renders its payload into the page as
<script type="application/json"> — that's how a section gets its props in the
first place. So any island can read any other section's data with no cooperation
from it:
1const header = useSectionProps('header') // by component name2const props = useSectionProps({ id }) // by section id34if (!header) return null // a merchant may have removed itIt re-reads when the theme editor swaps that section, so an edit doesn't leave you holding a stale payload.
getSectionProps(name) is the same read outside React — an event handler, a
module-level lookup. getAllSectionProps() dumps every mounted section, which is
useful in the console and too blunt for render.
Always handle
null. Reading another section's payload couples you to a section a merchant can remove in the editor at any time.
State is not public, and shouldn't be
You can't reach into a component and read its useState — it's private, and a
hook that could would break the moment that component re-rendered or unmounted.
What a component can do is publish:
1usePublish('pdp:variant', selected) // in the product section2const [variant] = useShared('pdp:variant') // anywhere elseThe publishing component decides what's part of its contract, instead of everything it happens to hold becoming one. The value clears when the publishing component unmounts, so a reader is never left holding state belonging to a section a merchant just deleted.
Shared state without a module
For state that isn't owned by anyone in particular, useShared is useState
across islands:
const [open, setOpen] = useShared('size-guide', false)Any island using the same key sees the same value. Keys are global — prefix them
with something you own (wishlist:ids, not ids).
Outside React: getShared, setShared and subscribeShared. clearShared
takes a key, a prefix: to clear a group, or nothing to clear everything.
When to still use createStore
A shared domain with actions, loading and error states and one obvious owner —
the cart is the example. It has addToCart, changeLine, a status, an error,
and every island agrees about it. That earns a module.
useShared is for ad-hoc wiring that doesn't deserve one. Writing a store file
just so two sections can agree on a boolean is ceremony.
See State across islands for why a module-level variable is enough in the first place.