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

fix(preact,svelte): empty target container before rendering client:only island (#13470)

* fix(preact,svelte): empty target container before rendering `client:only` island

* Remove log
This commit is contained in:
Matt Kane 2025-03-20 11:43:04 +00:00 committed by GitHub
parent 62595a00c6
commit ecadb6b02e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 41 additions and 5 deletions

View file

@ -0,0 +1,6 @@
---
'@astrojs/preact': patch
'@astrojs/svelte': patch
---
Hides fallback content when rendering `client:only` island

View file

@ -20,6 +20,9 @@ test.describe('Client only', () => {
const counter = await page.locator('#react-counter');
await expect(counter, 'component is visible').toBeVisible();
const fallback = await page.locator('[data-fallback=react]');
await expect(fallback, 'fallback content is hidden').not.toBeVisible();
const count = await counter.locator('pre');
await expect(count, 'initial count is 0').toHaveText('0');
@ -38,6 +41,10 @@ test.describe('Client only', () => {
const counter = await page.locator('#preact-counter');
await expect(counter, 'component is visible').toBeVisible();
const fallback = await page.locator('[data-fallback=preact]');
await expect(fallback, 'fallback content is hidden').not.toBeVisible();
const count = await counter.locator('pre');
await expect(count, 'initial count is 0').toHaveText('0');
@ -56,6 +63,9 @@ test.describe('Client only', () => {
const counter = await page.locator('#solid-counter');
await expect(counter, 'component is visible').toBeVisible();
const fallback = await page.locator('[data-fallback=solid]');
await expect(fallback, 'fallback content is hidden').not.toBeVisible();
const count = await counter.locator('pre');
await expect(count, 'initial count is 0').toHaveText('0');
@ -74,6 +84,9 @@ test.describe('Client only', () => {
const counter = await page.locator('#vue-counter');
await expect(counter, 'component is visible').toBeVisible();
const fallback = await page.locator('[data-fallback=vue]');
await expect(fallback, 'fallback content is hidden').not.toBeVisible();
const count = await counter.locator('pre');
await expect(count, 'initial count is 0').toHaveText('0');
@ -92,6 +105,9 @@ test.describe('Client only', () => {
const counter = await page.locator('#svelte-counter');
await expect(counter, 'component is visible').toBeVisible();
const fallback = await page.locator('[data-fallback=svelte]');
await expect(fallback, 'fallback content is hidden').not.toBeVisible();
const count = await counter.locator('pre');
await expect(count, 'initial count is 0').toHaveText('0');

View file

@ -19,22 +19,27 @@ import VueCounter from '../components/vue/VueCounter.vue';
<main>
<react.Counter id="react-counter" client:only="react">
<h1>react</h1>
<p slot="fallback" data-fallback="react">Loading React...</p>
</react.Counter>
<PreactCounter id="preact-counter" client:only="preact">
<h1>preact</h1>
<p slot="fallback" data-fallback="preact">Loading Preact...</p>
</PreactCounter>
<SolidCounter id="solid-counter" client:only="solid-js">
<h1>solid</h1>
<p slot="fallback" data-fallback="solid">Loading Solid...</p>
</SolidCounter>
<VueCounter id="vue-counter" client:only="vue">
<h1>vue</h1>
<p slot="fallback" data-fallback="vue">Loading Vue...</p>
</VueCounter>
<SvelteCounter id="svelte-counter" client:only="svelte">
<h1>svelte</h1>
<p slot="fallback" data-fallback="svelte">Loading Svelte...</p>
</SvelteCounter>
</main>
</body>

View file

@ -49,13 +49,19 @@ export default (element: HTMLElement) =>
}
}
const bootstrap = client !== 'only' ? hydrate : render;
bootstrap(
h(Component, props, children != null ? h(StaticHtml, { value: children }) : children),
element,
const child = h(
Component,
props,
children != null ? h(StaticHtml, { value: children }) : children,
);
if (client === 'only') {
element.innerHTML = '';
render(child, element);
} else {
hydrate(child, element);
}
// Preact has no "unmount" option, but you can use `render(null, element)`
element.addEventListener('astro:unmount', () => render(null, element), { once: true });
};

View file

@ -61,6 +61,9 @@ export default (element) => {
function createComponent(Component, target, props, shouldHydrate) {
let propsState = $state(props);
const bootstrap = shouldHydrate ? hydrate : mount;
if(!shouldHydrate) {
target.innerHTML = '';
}
const component = bootstrap(Component, { target, props: propsState });
return {
setProps(newProps) {