Preloading Data with 'use server'

I'm following the limited documentation, and I want to preload data from the server for a route:
import { Title } from "@solidjs/meta";
import { RouteDefinition, cache, createAsync } from "@solidjs/router";
import { getAbout } from "~/lib/about";

const getAboutPage = cache(async () => {
'use server';
return await getAbout();
}, 'about');

export const route = {
load: () => getAboutPage(),
} satisfies RouteDefinition;

export default function About() {

const about = createAsync(() => getAboutPage());

return about() && (
<>
<Title>About</Title>
<div class="flex items-center justify-center my-5">
<div class="border w-[400px] p-5 flex flex-col gap-3">
<h1 class="text-3xl font-semibold">{about()!.name}</h1>
<p>{about()!.description}</p>
</div>
</div>
</>
);
};
import { Title } from "@solidjs/meta";
import { RouteDefinition, cache, createAsync } from "@solidjs/router";
import { getAbout } from "~/lib/about";

const getAboutPage = cache(async () => {
'use server';
return await getAbout();
}, 'about');

export const route = {
load: () => getAboutPage(),
} satisfies RouteDefinition;

export default function About() {

const about = createAsync(() => getAboutPage());

return about() && (
<>
<Title>About</Title>
<div class="flex items-center justify-center my-5">
<div class="border w-[400px] p-5 flex flex-col gap-3">
<h1 class="text-3xl font-semibold">{about()!.name}</h1>
<p>{about()!.description}</p>
</div>
</div>
</>
);
};
I am preloading some data from a database. I'm not sure why the createAsync has an option for undefined, but I do about() as the docs suggest. However, the data does not display properly UNLESS I do full referesh. It does not stay when navigating back to the page. I only want to fetch it once, I just don't every want a blank page. You can see the example (without logging in) : https://solid-start-firebase.vercel.app/ How do I fix this? J
11 Replies
peerreynders
peerreynders5mo ago
I'm not sure why the createAsync has an option for undefined
Unless you supply it with an initialValue it's undefined before the async op settles. I view createAsync as the boundary between async values/events and the synchronous reactivity of Solid. Reactive values are continuous so they will start out as undefined unless they are given a specific value to start with. options
GitHub
solid-router/src/data/createAsync.ts at 1d0d4ffc5115962e41fce730f0c...
A universal router for Solid inspired by Ember and React Router - solidjs/solid-router
peerreynders
peerreynders5mo ago
This fixes the problem
export default function About() {
const about = createAsync(() => getAboutPage());

return (
<Show when={about()}>
{(data) => (
<>
<Title>About</Title>
<div class="flex items-center justify-center my-5">
<div class="border w-[400px] p-5 flex flex-col gap-3">
<h1 class="text-3xl font-semibold">{data().name}</h1>
<p>{data().description}</p>
</div>
</div>
</>
)}
</Show>
);
}
export default function About() {
const about = createAsync(() => getAboutPage());

return (
<Show when={about()}>
{(data) => (
<>
<Title>About</Title>
<div class="flex items-center justify-center my-5">
<div class="border w-[400px] p-5 flex flex-col gap-3">
<h1 class="text-3xl font-semibold">{data().name}</h1>
<p>{data().description}</p>
</div>
</div>
</>
)}
</Show>
);
}
The TSX area is also an effect. So about() && tsxEffect never let the TSX effect register during client side component creation when about() was still undefined. When refreshing, SSR + Suspense saved the day because it caught the promise and only (re?)created the component once the promise resolved. You have to let go of these "React-isms" which include using <For> instead of .map() otherwise things just won't work or de-optimize.
lxsmnsyc
lxsmnsyc5mo ago
first of all, the whole about() && (...) wouldn't work since it's a static expression, and as you know Solid components only evaluate once. You need to use Show for guaranteeing the value and Suspense to allow the SSR to wait for the data
jdgamble555
jdgamble5555mo ago
So this solves the problem where it doesn't load at all, but it still clearly jumps when you first load the page: - https://solid-start-firebase.vercel.app/about I just want it to load from the server after the data has been fetched. It shoud NEVER have the option to display a blank page. This is what it SHOULD look like - https://nextjs-firebase-todo.vercel.app/about
Create Next App
Generated by create next app
peerreynders
peerreynders5mo ago
I just want it to load from the server after the data has been fetched.
When does Next.js fetch that data? Before or after the navigation?
jdgamble555
jdgamble5555mo ago
I want it to load only on the server before the page is displayed... it would have to be after the navigation (as it wouldn't know what to fetch otherwise), but before the page load If you click on the link - https://solid-start-firebase.vercel.app/about - and click refresh, you see it jump... is this just how Solid works?
peerreynders
peerreynders5mo ago
If you are talking about the SSR behaviour try:
const about = createAsync(() => getAboutPage(),{ deferStream: true });
const about = createAsync(() => getAboutPage(),{ deferStream: true });
jdgamble555
jdgamble5555mo ago
Yup that fixed it. What does that do exactly?
peerreynders
peerreynders5mo ago
This is what it SHOULD look like
By default it starts the response ASAP to show something immediately and it then streams the resolved promise to update the page (progressive rendering). deferStream indicates to not release the response (suspense boundary?) until that async op has settled.
peerreynders
peerreynders5mo ago
DEV Community
Server Rendering in JavaScript: Optimizing Performance
If you read Server Rendering in JavaScript: Optimizing for Size you might be wondering what else is...
DEV Community
Marko for Sites, Solid for Apps
I've been sitting on writing this article for 2 years. In my heart this was the article I was going...
No description
jdgamble555
jdgamble5555mo ago
ok got it thanks! so it does work without it, just with streaming... makes sense
Want results from more Discord servers?
Add your server