Skip to content

Commit

Permalink
fix(rendering): allow render instructions to propagate while renderin…
Browse files Browse the repository at this point in the history
…g slots (#10316)

* fix(rendering): allow render instructions to propagate while rendering slots

* add test

* add changeset

* undo changes to `playwright.config.js`
  • Loading branch information
lilnasy authored Mar 5, 2024
1 parent 439155c commit 507b4ac
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/sharp-scissors-think.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"astro": patch
---

Fixes an issue where slotting interactive components within a "client:only" component prevented all component code in the page from running.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
import ReactCounter from '../components/react/ReactCounter.jsx';
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
</head>
<body>
<main>
<ReactCounter id="react-counter" client:only="react">
<Fragment><ReactCounter id="react-counter-nested" client:only="react" children/></Fragment>
</ReactCounter>
</main>
</body>
</html>
10 changes: 10 additions & 0 deletions packages/astro/e2e/nested-in-react.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,14 @@ test.describe('Nested Frameworks in React', () => {

await expect(count, 'count incremented by 1').toHaveText('1');
});

test('React counter nested in client:only component', async ({ astro, page }) => {
await page.goto(astro.resolveUrl('/nested-in-only'));

const counter = page.locator('#react-counter');
await expect(counter, 'component is visible').toBeVisible();

const count = counter.locator('#react-counter-count');
await expect(count).toBeVisible();
});
});
12 changes: 10 additions & 2 deletions packages/astro/src/runtime/server/render/slot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,16 @@ export async function renderSlotToString(
let instructions: null | RenderInstruction[] = null;
const temporaryDestination: RenderDestination = {
write(chunk) {
if (chunk instanceof Response) return;
if (typeof chunk === 'object' && 'type' in chunk && typeof chunk.type === 'string') {
// if the chunk is already a SlotString, we concatenate
if (chunk instanceof SlotString) {
content += chunk
if (chunk.instructions) {
instructions ??= []
instructions.push(...chunk.instructions)
}
}
else if (chunk instanceof Response) return;
else if (typeof chunk === 'object' && 'type' in chunk && typeof chunk.type === 'string') {
if (instructions === null) {
instructions = [];
}
Expand Down

0 comments on commit 507b4ac

Please sign in to comment.