summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/sharp-scissors-think.md5
-rw-r--r--packages/astro/e2e/fixtures/nested-in-react/src/pages/nested-in-only.astro17
-rw-r--r--packages/astro/e2e/nested-in-react.test.js10
-rw-r--r--packages/astro/src/runtime/server/render/slot.ts12
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 = [];
}