Solid +Astro SSR + Data Fetching on hydration

Hi! I working on an Astro site with Solid and I am having trouble getting Solid to fetch data. I would like to only fetch the component has been hydrated, but can't seem to get it to work. I am trying to detect if we are on the client by looking if window is defined. The console logs are correct, but the fetch is never triggered. What am I doing wrong? Please keep in mind this is the 1st time I am using Solid
const fetchCurrent = async (isSSR: boolean) => {
console.log("fetching...", isSSR);

if (isSSR) return;
await new Promise((resolve) => setTimeout(resolve, 4000));
const response = await fetch("/api/currently/reading");
return response.json() as Promise<Book>;
};

export default function CurrentRead() {
const [isSSR] = createSignal(typeof window === "undefined");
const [current] = createResource(isSSR, fetchCurrent);

createEffect(() => {
console.log(">> ssr", isSSR());
}, [isSSR]);

return (
<>
<span>fooo</span>
<Show when={current.loading}>
<p>Loading...</p>
</Show>
<Switch>
<Match when={current.error}>
<span>Error</span>
</Match>
<Match when={current()}>
<div>{JSON.stringify(current())}</div>
</Match>
</Switch>
</>
);
}
const fetchCurrent = async (isSSR: boolean) => {
console.log("fetching...", isSSR);

if (isSSR) return;
await new Promise((resolve) => setTimeout(resolve, 4000));
const response = await fetch("/api/currently/reading");
return response.json() as Promise<Book>;
};

export default function CurrentRead() {
const [isSSR] = createSignal(typeof window === "undefined");
const [current] = createResource(isSSR, fetchCurrent);

createEffect(() => {
console.log(">> ssr", isSSR());
}, [isSSR]);

return (
<>
<span>fooo</span>
<Show when={current.loading}>
<p>Loading...</p>
</Show>
<Switch>
<Match when={current.error}>
<span>Error</span>
</Match>
<Match when={current()}>
<div>{JSON.stringify(current())}</div>
</Match>
</Switch>
</>
);
}
3 Replies
snailyluke
snailyluke7mo ago
A couple things: 1. solid-js/web actually exports an isServer, which you can use to check if you’re server rendering. So no need to define it yourself! 2. Your isSSR signal (and Solid’s isServer for that matter) isn’t really reactive. Even though the value technically “changes” when it goes from the server to the client, the server is a separate reactive context from the client. So the change in value won’t be detected on hydration and the resource won’t run again. So it being a signal doesn’t actually do anything here to refetch the resource. A signal from createSignal only triggers effects if its setter is called and changes the value. Otherwise it won’t do anything. Since you’re not creating or using a setIsSSR (because why would you for this?), it won’t trigger the refetch. Also, Astro runs your Solid components inside a Suspense block, which (I believe) means that resources will all run on SSR and not on hydration (but can still be re-run client-side). This behavior in Astro is relatively new though so I might have a few things wrong I would recommend changing the isSSR to Solid’s isServer, or using Vite’s import.meta.env.SSR, and just check it directly in your fetchCurrent function rather than passing it in as a signal (though either way is fine! It’s just not reactive) Then I’d take the refetch method that createResource returns, and call it inside an onMount or createEffect - it’s the same either way, I just like onMount if I know I’m only running something once. Alternatively, you could keep the code you have and just try setting isSSR again in an onMount function or other event handler, which should lead to a refetch as well. ALTERNATIVE alternatively, if you don’t need this component to render on the server at all, because the markup depends on the data you’re fetching, you could use a client:only=“solid-js” on the Solid component in the Astro file
terenced
terencedOP7mo ago
Thank you @snailyluke! isServer and refetch work great! I needed to also Suspense in my component instead of Show/Match/Switch, but I think the code seems cleaner with the suspense. Thanks again! 😄
snailyluke
snailyluke7mo ago
Oh yeah for sure, suspense is the way to go there too! No problem 😊
Want results from more Discord servers?
Add your server