0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-04-07 23:41:43 -05:00

fix(slots): consume eagerly rendered slot after one use (#8929)

* render slots lazily

* add test

* add changeset

* refactor

* reword changeset
This commit is contained in:
Arsh 2023-11-01 13:53:38 +00:00 committed by GitHub
parent 4a0fec969f
commit 2da33b7a13
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 59 additions and 2 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fixes an issue where rendering the same slot multiple times invoked it only once.

View file

@ -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);
};
}
}

View file

@ -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);
}
});
});

View file

@ -0,0 +1,6 @@
---
const randomNumber = Math.random();
---
<div>
{randomNumber}
</div>

View file

@ -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} />
)}

View file

@ -0,0 +1,7 @@
---
import RandomCard from '../components/Random.astro';
import RenderMulti from '../components/RenderMultipleTimes.astro';
---
<RenderMulti count={10}>
<RandomCard/>
</RenderMulti>