diff options
-rw-r--r-- | .changeset/sharp-scissors-think.md | 5 | ||||
-rw-r--r-- | packages/astro/e2e/fixtures/nested-in-react/src/pages/nested-in-only.astro | 17 | ||||
-rw-r--r-- | packages/astro/e2e/nested-in-react.test.js | 10 | ||||
-rw-r--r-- | packages/astro/src/runtime/server/render/slot.ts | 12 |
4 files changed, 42 insertions, 2 deletions
diff --git a/.changeset/sharp-scissors-think.md b/.changeset/sharp-scissors-think.md new file mode 100644 index 000000000..60498d213 --- /dev/null +++ b/.changeset/sharp-scissors-think.md @@ -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. diff --git a/packages/astro/e2e/fixtures/nested-in-react/src/pages/nested-in-only.astro b/packages/astro/e2e/fixtures/nested-in-react/src/pages/nested-in-only.astro new file mode 100644 index 000000000..689632947 --- /dev/null +++ b/packages/astro/e2e/fixtures/nested-in-react/src/pages/nested-in-only.astro @@ -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> diff --git a/packages/astro/e2e/nested-in-react.test.js b/packages/astro/e2e/nested-in-react.test.js index 7fbe13c0b..db9eeb0dd 100644 --- a/packages/astro/e2e/nested-in-react.test.js +++ b/packages/astro/e2e/nested-in-react.test.js @@ -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(); + }); }); diff --git a/packages/astro/src/runtime/server/render/slot.ts b/packages/astro/src/runtime/server/render/slot.ts index 53e820e5c..549c639a5 100644 --- a/packages/astro/src/runtime/server/render/slot.ts +++ b/packages/astro/src/runtime/server/render/slot.ts @@ -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 = []; } |