ClientReady#56
Conversation
Introduce a scope for managing XML namespaces. This allows for proper handling of SVG and MathML elements within nested structures, including reactive branches and teleported content. This change also improves the `createContainer` logic by inheriting namespaces from parent scopes and setting them explicitly when needed, rather than relying on string manipulation or re-serialization.
Introduce ClientReady component and move ClientOnly into client-boundaries.js. Update package.json and documentation to reflect the changes.
Review Summary by QodoIntroduce ClientReady component and refactor client boundaries
WalkthroughsDescription• Introduce ClientReady component for async-aware client rendering • Consolidate ClientOnly into new client-boundaries.js module • Update exports and documentation to reflect new structure • Add comprehensive tests for ClientReady behavior Diagramflowchart LR
A["client-only.js<br/>ClientOnly"] -->|consolidate| B["client-boundaries.js<br/>ClientOnly + ClientReady"]
B -->|export| C["package.json<br/>Updated exports"]
B -->|document| D["Documentation<br/>ClientOnly & ClientReady"]
B -->|test| E["Tests<br/>ClientReady scenarios"]
File Changes1. packages/retend-server/source/client-boundaries.js
|
Code Review by Qodo
1. Fallback/content overlap
|
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
retend | 95d851a | Commit Preview URL Branch Preview URL |
May 10 2026, 03:40 PM |
| export function ClientReady(props) { | ||
| const { children, fallback } = props; | ||
| const ready = Cell.source(false); | ||
|
|
||
| const ClientReadyContent = () => { | ||
| onSetup(() => ready.set(true)); | ||
| return children; | ||
| }; | ||
|
|
||
| return [ | ||
| ClientOnly({ | ||
| children: () => | ||
| Await({ | ||
| children: ClientReadyContent, | ||
| }), | ||
| }), | ||
| If(ready, { | ||
| false: () => fallback, | ||
| }), | ||
| ]; |
There was a problem hiding this comment.
1. Fallback/content overlap 🐞 Bug ≡ Correctness
ClientReady can briefly render the resolved client subtree while still rendering fallback, because ready is flipped in an onSetup effect that runs after the DOM has already been updated to show the Await content. This can produce a flash/layout shift (content appears before fallback is removed) and breaks the promise that the fallback remains until the subtree is ready, then disappears.
Agent Prompt
### Issue description
`ClientReady` currently renders fallback via a separate `If(ready)` sibling, but only sets `ready` in an `onSetup` effect inside the awaited subtree. Because Retend applies DOM updates before running `onSetup` effects (and activation is delayed), the awaited content can become visible while the fallback is still rendered, causing a brief overlap/layout shift.
### Issue Context
`Await` already supports `fallback` and will keep rendering it until its initial async dependencies resolve. `ClientOnly` can also render the same `fallback` during SSR/before mount.
### Fix Focus Areas
- packages/retend-server/source/client-boundaries.js[84-103]
### Suggested fix
Refactor `ClientReady` to rely on `ClientOnly` + `Await` fallback instead of a separate `ready` cell:
```js
export function ClientReady(props) {
const { children, fallback } = props;
return ClientOnly({
fallback,
children: () =>
Await({
fallback: fallback ?? null,
children,
}),
});
}
```
This keeps the fallback in exactly one place and prevents the “content appears before fallback is removed” window.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
No description provided.