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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user