From d58e8cc7b8ee86e13b97ce3422f51f41dfc72e6d Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Thu, 26 May 2022 14:35:41 -0500 Subject: [PATCH] fix(#3362): fix client:only behavior for React, Vue, Solid --- packages/integrations/react/client.js | 7 ++++--- packages/integrations/solid/client.js | 14 ++++++++++---- packages/integrations/svelte/client.js | 5 +++-- packages/integrations/vue/client.js | 15 +++++++++++---- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/packages/integrations/react/client.js b/packages/integrations/react/client.js index d5d84884745b1..2828d2cbe3ac9 100644 --- a/packages/integrations/react/client.js +++ b/packages/integrations/react/client.js @@ -12,18 +12,19 @@ function isAlreadyHydrated(element) { export default (element) => (Component, props, children, { client }) => { + if (!element.hasAttribute('ssr')) return; const componentEl = createElement( Component, props, children != null ? createElement(StaticHtml, { value: children }) : children ); - if (client === 'only') { - return createRoot(element).render(componentEl); - } const rootKey = isAlreadyHydrated(element); // HACK: delete internal react marker for nested components to suppress agressive warnings if (rootKey) { delete element[rootKey]; } + if (client === 'only') { + return createRoot(element).render(componentEl); + } return hydrateRoot(element, componentEl); }; diff --git a/packages/integrations/solid/client.js b/packages/integrations/solid/client.js index d31c5cecd1ecb..005f3c980376a 100644 --- a/packages/integrations/solid/client.js +++ b/packages/integrations/solid/client.js @@ -1,21 +1,27 @@ import { sharedConfig } from 'solid-js'; -import { hydrate, createComponent } from 'solid-js/web'; +import { hydrate, render, createComponent } from 'solid-js/web'; -export default (element) => (Component, props, childHTML) => { +export default (element) => (Component, props, childHTML, { client }) => { // Prepare global object expected by Solid's hydration logic if (!window._$HY) { window._$HY = { events: [], completed: new WeakSet(), r: {} }; } + if (!element.hasAttribute('ssr')) return; + + const fn = client === 'only' ? render : hydrate; + // Perform actual hydration let children; - hydrate( + fn( () => createComponent(Component, { ...props, get children() { if (childHTML != null) { // hydrating - if (sharedConfig.context) children = element.querySelector('astro-fragment'); + if (sharedConfig.context) { + children = element.querySelector('astro-fragment'); + } if (children == null) { children = document.createElement('astro-fragment'); diff --git a/packages/integrations/svelte/client.js b/packages/integrations/svelte/client.js index c10c7afa01b04..3f401b544f940 100644 --- a/packages/integrations/svelte/client.js +++ b/packages/integrations/svelte/client.js @@ -1,13 +1,14 @@ import SvelteWrapper from './Wrapper.svelte'; export default (target) => { - return (component, props, children) => { + return (component, props, children, { client }) => { + if (!target.hasAttribute('ssr')) return; delete props['class']; try { new SvelteWrapper({ target, props: { __astro_component: component, __astro_children: children, ...props }, - hydrate: true, + hydrate: client !== 'only', }); } catch (e) {} }; diff --git a/packages/integrations/vue/client.js b/packages/integrations/vue/client.js index 0ba4e81063ab7..4832a984760bc 100644 --- a/packages/integrations/vue/client.js +++ b/packages/integrations/vue/client.js @@ -1,14 +1,21 @@ -import { h, createSSRApp } from 'vue'; +import { h, createSSRApp, createApp } from 'vue'; import StaticHtml from './static-html.js'; -export default (element) => (Component, props, children) => { +export default (element) => (Component, props, children, { client }) => { delete props['class']; + if (!element.hasAttribute('ssr')) return; + // Expose name on host component for Vue devtools const name = Component.name ? `${Component.name} Host` : undefined; const slots = {}; if (children != null) { slots.default = () => h(StaticHtml, { value: children }); } - const app = createSSRApp({ name, render: () => h(Component, props, slots) }); - app.mount(element, true); + if (client === 'only') { + const app = createApp({ name, render: () => h(Component, props, slots) }); + app.mount(element, false); + } else { + const app = createSSRApp({ name, render: () => h(Component, props, slots) }); + app.mount(element, true); + } };