diff options
author | 2023-11-01 13:53:38 +0000 | |
---|---|---|
committer | 2023-11-01 19:23:38 +0530 | |
commit | 2da33b7a13cf964595f758e3e4a865fd97d0943e (patch) | |
tree | df4b84ccf5e5216aec35b12a0af35641ff9cc35e | |
parent | 4a0fec969fac93c905b32952128572889d90a6ef (diff) | |
download | astro-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
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 |