diff options
Diffstat (limited to 'packages/integrations/solid/src/client.ts')
-rw-r--r-- | packages/integrations/solid/src/client.ts | 67 |
1 files changed, 41 insertions, 26 deletions
diff --git a/packages/integrations/solid/src/client.ts b/packages/integrations/solid/src/client.ts index a47c5310d..f2020bb56 100644 --- a/packages/integrations/solid/src/client.ts +++ b/packages/integrations/solid/src/client.ts @@ -1,10 +1,12 @@ import { Suspense } from 'solid-js'; +import { createStore, reconcile } from 'solid-js/store'; import { createComponent, hydrate, render } from 'solid-js/web'; +const alreadyInitializedElements = new WeakMap<Element, any>(); + export default (element: HTMLElement) => (Component: any, props: any, slotted: any, { client }: { client: string }) => { if (!element.hasAttribute('ssr')) return; - const isHydrate = client !== 'only'; const bootstrap = isHydrate ? hydrate : render; @@ -32,31 +34,44 @@ export default (element: HTMLElement) => const { default: children, ...slots } = _slots; const renderId = element.dataset.solidRenderId; + if (alreadyInitializedElements.has(element)) { + // update the mounted component + alreadyInitializedElements.get(element)!( + // reconcile will make sure to apply as little updates as possible, and also remove missing values w/o breaking reactivity + reconcile({ + ...props, + ...slots, + children, + }), + ); + } else { + const [store, setStore] = createStore({ + ...props, + ...slots, + children, + }); + // store the function to update the current mounted component + alreadyInitializedElements.set(element, setStore); - const dispose = bootstrap( - () => { - const inner = () => - createComponent(Component, { - ...props, - ...slots, - children, - }); + const dispose = bootstrap( + () => { + const inner = () => createComponent(Component, store); - if (isHydrate) { - return createComponent(Suspense, { - get children() { - return inner(); - }, - }); - } else { - return inner(); - } - }, - element, - { - renderId, - }, - ); - - element.addEventListener('astro:unmount', () => dispose(), { once: true }); + if (isHydrate) { + return createComponent(Suspense, { + get children() { + return inner(); + }, + }); + } else { + return inner(); + } + }, + element, + { + renderId, + }, + ); + element.addEventListener('astro:unmount', () => dispose(), { once: true }); + } }; |