docs(react-islands): drop the write-during-render guard

Implemented and removed. A render-phase flag cleared on a microtask is
still set when React runs effects, so islands writing from an effect —
the documented correct pattern — would throw. The flag also cannot be
set for an island's own re-renders, so real violations pass silently.

Detecting React's render phase reliably needs React internals, which is
not acceptable in a shipped framework. React already reports the real
hazard, and the getSnapshot caching requirement covers the loop case.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 15:33:48 +05:30
co-authored by Claude Opus 5
parent 01a3b3b4e9
commit 5f66c8129c
@@ -127,9 +127,9 @@ record that subscribers and devtools depend on.
Write → action → store notifies → snapshot changes → island re-renders. This terminates cleanly
**provided writes never occur during render**. Writes belong in event handlers or effects.
This rule is enforced in dev (see Error handling), not merely documented. It is also the reason
this shape was chosen over generated `bind:` sugar: the cycle stays visible in the author's own
code rather than being hidden in generated glue.
This rule is documented rather than machine-enforced — see "Dropped: the write-during-render
guard" below. It is also the reason this shape was chosen over generated `bind:` sugar: the
cycle stays visible in the author's own code rather than being hidden in generated glue.
## Compiler and bundler changes
@@ -189,12 +189,38 @@ point.
| Island bundle fails to load | Placeholder remains, warning logged; page stays functional because everything else was server-rendered |
| Non-serializable props | Compile-time `WRN-ISLAND-PROPS` |
| Unknown store name | Dev: throw, listing available store names. Prod: warn, return undefined |
| Action fired during render | Dev: throw with a targeted message pointing at the handler/effect rule (React's own warning is too generic to diagnose quickly) |
| Action fired during render | Left to React. See "Dropped: the write-during-render guard" below. |
| Cleanup throws on unmount | Caught and logged; navigation must not break |
Islands failing **locally** is the most valuable property of this model: a crashed chart leaves
the rest of the page working.
## Dropped: the write-during-render guard
The design originally called for a dev-only guard that threw when an island
called a store action during render. It was implemented, then removed: the
mechanism is unreliable in both directions.
- **False positives.** React runs effects before a queued microtask drains, so a
render-phase flag cleared on a microtask is still set inside `useEffect`. An
island writing from an effect — the documented correct pattern — would throw.
- **False negatives.** The flag can only be set from the error boundary`s
render. When an island updates its own state, only the island re-renders, so
the flag is never set and a genuine write-during-render passes silently.
There is no reliable public API for detecting React`s render phase; doing it
properly requires React internals, which is not acceptable in a shipped
framework.
React already covers the real hazard: writing during render that notifies
subscribers produces "Cannot update a component while rendering a different
component", and the infinite-loop case is caught by the `getSnapshot` caching
requirement handled in the store bridge. The custom guard added false positives
without covering anything React misses.
The author-facing rule still stands and is still documented — it is simply not
machine-enforced.
## Testing
### Compiler unit tests