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:
parent
4a0fec969f
commit
2da33b7a13
6 changed files with 59 additions and 2 deletions
5
.changeset/plenty-spiders-act.md
Normal file
5
.changeset/plenty-spiders-act.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fixes an issue where rendering the same slot multiple times invoked it only once.
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
6
packages/astro/test/fixtures/astro-slots/src/components/Random.astro
vendored
Normal file
6
packages/astro/test/fixtures/astro-slots/src/components/Random.astro
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
const randomNumber = Math.random();
|
||||
---
|
||||
<div>
|
||||
{randomNumber}
|
||||
</div>
|
15
packages/astro/test/fixtures/astro-slots/src/components/RenderMultipleTimes.astro
vendored
Normal file
15
packages/astro/test/fixtures/astro-slots/src/components/RenderMultipleTimes.astro
vendored
Normal 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} />
|
||||
)}
|
7
packages/astro/test/fixtures/astro-slots/src/pages/rendered-multiple-times.astro
vendored
Normal file
7
packages/astro/test/fixtures/astro-slots/src/pages/rendered-multiple-times.astro
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
import RandomCard from '../components/Random.astro';
|
||||
import RenderMulti from '../components/RenderMultipleTimes.astro';
|
||||
---
|
||||
<RenderMulti count={10}>
|
||||
<RandomCard/>
|
||||
</RenderMulti>
|
Loading…
Add table
Reference in a new issue