summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Arsh <69170106+lilnasy@users.noreply.github.com> 2023-11-01 13:53:38 +0000
committerGravatar GitHub <noreply@github.com> 2023-11-01 19:23:38 +0530
commit2da33b7a13cf964595f758e3e4a865fd97d0943e (patch)
treedf4b84ccf5e5216aec35b12a0af35641ff9cc35e
parent4a0fec969fac93c905b32952128572889d90a6ef (diff)
downloadastro-2da33b7a13cf964595f758e3e4a865fd97d0943e.tar.gz
astro-2da33b7a13cf964595f758e3e4a865fd97d0943e.tar.zst
astro-2da33b7a13cf964595f758e3e4a865fd97d0943e.zip
fix(slots): consume eagerly rendered slot after one use (#8929)
* render slots lazily * add test * add changeset * refactor * reword changeset
-rw-r--r--.changeset/plenty-spiders-act.md5
-rw-r--r--packages/astro/src/runtime/server/render/astro/instance.ts14
-rw-r--r--packages/astro/test/astro-slots.test.js14
-rw-r--r--packages/astro/test/fixtures/astro-slots/src/components/Random.astro6
-rw-r--r--packages/astro/test/fixtures/astro-slots/src/components/RenderMultipleTimes.astro15
-rw-r--r--packages/astro/test/fixtures/astro-slots/src/pages/rendered-multiple-times.astro7
6 files changed, 59 insertions, 2 deletions
diff --git a/.changeset/plenty-spiders-act.md b/.changeset/plenty-spiders-act.md
new file mode 100644
index 000000000..0238e12f4
--- /dev/null
+++ b/.changeset/plenty-spiders-act.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fixes an issue where rendering the same slot multiple times invoked it only once.
diff --git a/packages/astro/src/runtime/server/render/astro/instance.ts b/packages/astro/src/runtime/server/render/astro/instance.ts
index 0748cbbb3..083a8242c 100644
--- a/packages/astro/src/runtime/server/render/astro/instance.ts
+++ b/packages/astro/src/runtime/server/render/astro/instance.ts
@@ -31,8 +31,18 @@ export class AstroComponentInstance {
this.factory = factory;
this.slotValues = {};
for (const name in slots) {
- const value = slots[name](result);
- this.slotValues[name] = () => value;
+ // prerender the slots eagerly to make collection entries propagate styles and scripts
+ let didRender = false;
+ let value = slots[name](result);
+ this.slotValues[name] = () => {
+ // use prerendered value only once
+ if (!didRender) {
+ didRender = true;
+ return value;
+ }
+ // render afresh for the advanced use-case where the same slot is rendered multiple times
+ return slots[name](result);
+ };
}
}
diff --git a/packages/astro/test/astro-slots.test.js b/packages/astro/test/astro-slots.test.js
index 10422d745..28f949690 100644
--- a/packages/astro/test/astro-slots.test.js
+++ b/packages/astro/test/astro-slots.test.js
@@ -148,5 +148,19 @@ describe('Slots', () => {
expect($('#render-args span')).to.have.lengthOf(1);
expect($('#render-args').text()).to.equal('render-args');
}
+
+ {
+ const html = await fixture.readFile('/rendered-multiple-times/index.html');
+ const $ = cheerio.load(html);
+
+ const elements = $('div');
+ expect(elements).to.have.lengthOf(10);
+
+ const [ first, second, third ] = elements;
+
+ expect(first.children[0].data).to.not.equal(second.children[0].data);
+ expect(second.children[0].data).to.not.equal(third.children[0].data);
+ expect(third.children[0].data).to.not.equal(first.children[0].data);
+ }
});
});
diff --git a/packages/astro/test/fixtures/astro-slots/src/components/Random.astro b/packages/astro/test/fixtures/astro-slots/src/components/Random.astro
new file mode 100644
index 000000000..1b845887b
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-slots/src/components/Random.astro
@@ -0,0 +1,6 @@
+---
+const randomNumber = Math.random();
+---
+<div>
+ {randomNumber}
+</div> \ No newline at end of file
diff --git a/packages/astro/test/fixtures/astro-slots/src/components/RenderMultipleTimes.astro b/packages/astro/test/fixtures/astro-slots/src/components/RenderMultipleTimes.astro
new file mode 100644
index 000000000..3689a1d8c
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-slots/src/components/RenderMultipleTimes.astro
@@ -0,0 +1,15 @@
+---
+interface Props {
+ count: number;
+}
+const {count} = Astro.props;
+
+const renders: string[] = [];
+for (let i = 0; i < count; i++) {
+ renders.push(await Astro.slots.render('default'));
+}
+---
+
+{renders.map(
+ (render, i) => <Fragment key={i} set:html={render} />
+)} \ No newline at end of file
diff --git a/packages/astro/test/fixtures/astro-slots/src/pages/rendered-multiple-times.astro b/packages/astro/test/fixtures/astro-slots/src/pages/rendered-multiple-times.astro
new file mode 100644
index 000000000..bd215a4a6
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-slots/src/pages/rendered-multiple-times.astro
@@ -0,0 +1,7 @@
+---
+import RandomCard from '../components/Random.astro';
+import RenderMulti from '../components/RenderMultipleTimes.astro';
+---
+<RenderMulti count={10}>
+ <RandomCard/>
+</RenderMulti> \ No newline at end of file