S
SolidJS•15mo ago
aquarazorda

[Solved] Reactivity problem when refreshing the page

I've got a route, where I'm fetching data with server$ function, which sits inside createResource and it works fine, when I'm navigating. But when I'm refreshing, I can see that it fetches on the server, but Resource doesn't get updated on client side. What am I doing wrong?
const [data] = fetchFolders();
createEffect(() => console.log(data()));
const [data] = fetchFolders();
createEffect(() => console.log(data()));
this is the client side, which doesn't log fetched data when reloading. this is the server side
const fetchFolders_ = server$(async () =>
await fetch("url")
.then(res => res.json()
));

export const fetchFolders = () => createResource(fetchFolders_);
const fetchFolders_ = server$(async () =>
await fetch("url")
.then(res => res.json()
));

export const fetchFolders = () => createResource(fetchFolders_);
Basically what I'm trying to achieve is that, I only want to export from server with already server$ wrapped functions and since I'm making an api call from server, I want it to be cached, I'll use solid-query or solid-cache for it. In this example, to make it simple, I'm using createResource and as mentioned, everything works fine when I'm navigating to the page where I have that logic, but if I refresh, promise doesn't get resolved and it's always in loading state, but on server side, I can see that promise resolved. This happens with routeData as well. Solution When I was accessing data, I had it wrapped with <Show> component and I was only showing data, when data.loading was false. Wrapping it with <Suspense> was the solution.
46 Replies
aquarazorda
aquarazorda•15mo ago
This is the response by GPT4 😄 ---- GPT START ---- It seems like the issue you're experiencing is due to not properly handling server-side rendering (SSR) and hydration. In this case, you need to make sure that the data fetched on the server is passed to the client and properly hydrated. To fix this issue, update your createResource call by providing ResourceOptions with ssrLoadFrom set to "server". This will tell Solid to load the data from the server during SSR:
export const fetchFolders = () =>
createResource(fetchFolders_, {
ssrLoadFrom: "server",
});
export const fetchFolders = () =>
createResource(fetchFolders_, {
ssrLoadFrom: "server",
});
Now, you need to make sure that the server-rendered data is properly passed to the client. In your server-side rendering code, you should use renderToString from "solid-js/web" and runServerEffects from "solid-js/server" to render your app and execute server effects:
import { renderToString } from "solid-js/web";
import { runServerEffects } from "solid-js/server";

async function renderApp() {
const [html, data] = await runServerEffects(() => renderToString(App));
// Pass the `data` object to the client
}
import { renderToString } from "solid-js/web";
import { runServerEffects } from "solid-js/server";

async function renderApp() {
const [html, data] = await runServerEffects(() => renderToString(App));
// Pass the `data` object to the client
}
Finally, on the client side, you need to hydrate your app with the data received from the server:
import { hydrate } from "solid-js/web";

hydrate(App, document.getElementById("app"), dataFromServer);
import { hydrate } from "solid-js/web";

hydrate(App, document.getElementById("app"), dataFromServer);
By making these changes, the data fetched on the server should be properly passed to the client and used when hydrating the app. This should resolve the issue of the Resource not being updated on the client side when refreshing the page. ----GPT END--- I've asked this question in couple of channels, but seems like nobody has an idea what's going on and this been sitting here for almost a day now. I hope you don't mind tagging you @core-team This seems like the last problem which I have with Solid for now and I'm ready to start working on some big projects with it. I've already pitched to my team and products team to rewrite whole website with Solid and they are impressed.
lxsmnsyc
lxsmnsyc•15mo ago
there's no such thing as runServerEffects tbf the question isn't quite clear
aquarazorda
aquarazorda•15mo ago
@lxsmnsyc that console.log in createEffect writes undefined first and then the data, only when I navigate to that page, where I use it. So that loading status also changes to false, but when I’m refreshing the page, it only logs undefined and loading is always true, but server sends the request and gets the data, but that resource doesn’t get updated. Can’t understand why it doesn’t work on page refresh.
lxsmnsyc
lxsmnsyc•15mo ago
by refresh I assume you meant page reload/initial page load?
aquarazorda
aquarazorda•15mo ago
Yes, exactly. Sorry, English isn't my first language.
lxsmnsyc
lxsmnsyc•15mo ago
hmmm, okay, do you have some repro for this? or a video of the said behavior
lxsmnsyc
lxsmnsyc•15mo ago
hmmm okay thank you. What's your SSR mode currently? Sync, Async or Stream?
aquarazorda
aquarazorda•15mo ago
lxsmnsyc
lxsmnsyc•15mo ago
you can check out entry-server
aquarazorda
aquarazorda•15mo ago
ah, it's async
aquarazorda
aquarazorda•15mo ago
aquarazorda
aquarazorda•15mo ago
@lxsmnsyc just checked, it only works correctly when using renderSync
lxsmnsyc
lxsmnsyc•15mo ago
yeah it would if it was Sync maybe a bug with async
aquarazorda
aquarazorda•15mo ago
same thing happens with stream gotcha, will continue with sync for now. Thanks for your time and sorry for disturbing
lxsmnsyc
lxsmnsyc•15mo ago
Time to mention @ryansolid
aquarazorda
aquarazorda•15mo ago
when that promise resolves, whole page gets destroyed confusednick @lxsmnsyc I guess I’m out of luck here 😬
lxsmnsyc
lxsmnsyc•15mo ago
what happens if you add Suspense to the component that reads data and try removing the createEffect
aquarazorda
aquarazorda•15mo ago
@lxsmnsyc if you check the 2nd video, I've got createEffect removed, plus that index.tsx is a FileRoute, do I need to wrap it with Suspense? There's a Suspense in the root.tsx, I'm using SolidStart
lxsmnsyc
lxsmnsyc•15mo ago
yeah my concern is just what happens if Suspense is granular than relying on the root we don't really recommend having a single Suspense boundary in the entire app
aquarazorda
aquarazorda•15mo ago
So should I wrap <FileRoutes /> with Suspense? That's what you meant? just tested, it doesn't work
lxsmnsyc
lxsmnsyc•15mo ago
No, just the component that reads data e.g.
const [data] = fetchFolders();

return (
<Suspense>
<SomeOtherComp data={data()} />
</Suspense>
);
const [data] = fetchFolders();

return (
<Suspense>
<SomeOtherComp data={data()} />
</Suspense>
);
aquarazorda
aquarazorda•15mo ago
Gotcha, I'm reading data with routeData, that's what confused me, checking.
lxsmnsyc
lxsmnsyc•15mo ago
then wrap it around the element that reads from useRouteData
aquarazorda
aquarazorda•15mo ago
interesting, now I see an error, instead of whole page going blank and that data is undefined seems like
lxsmnsyc
lxsmnsyc•15mo ago
const data = useRouteData();

return (
<Suspense>
<SomeOtherComp data={data()} />
</Suspense>
);
const data = useRouteData();

return (
<Suspense>
<SomeOtherComp data={data()} />
</Suspense>
);
aquarazorda
aquarazorda•15mo ago
now promise resolves, I don't see that it's loading anymore but data is undefined
lxsmnsyc
lxsmnsyc•15mo ago
resources are always undefined initially, I guess you're trying to access some property that causes some render error like
data().something
data().something
where in reality it is
(undefined).something
(undefined).something
that's just my assumption
aquarazorda
aquarazorda•15mo ago
that data never gets a value, when using suspense yup, I've fixed it so the thing is that, data never gets a value it's always undefined
lxsmnsyc
lxsmnsyc•15mo ago
without a repro I cannot really say the exact issue
aquarazorda
aquarazorda•15mo ago
but I see that it's being fetched and there's a value
aquarazorda
aquarazorda•15mo ago
I'll push it, need couple of minutes, thanks for your help!
lxsmnsyc
lxsmnsyc•15mo ago
you didn't mention you were using createCachedResource
aquarazorda
aquarazorda•15mo ago
I swapped it out now, same thing happens with createResource @lxsmnsyc I just want to know, am I doing something wrong here or is it a bug, because it works on renderSync and not with others and I have to wait for it to be fixed and continue what I'm doing.
lxsmnsyc
lxsmnsyc•15mo ago
It works on renderSync because resources are skipped in the server Without a repro I cannot tell the exact issue. I cannot use this repo for issue reproduction
aquarazorda
aquarazorda•15mo ago
should I create a plain solid-start repo and reproduce the issue there?
lxsmnsyc
lxsmnsyc•15mo ago
yes basic reproduction please, at least only solid-start and solid-js
aquarazorda
aquarazorda•15mo ago
@lxsmnsyc https://stackblitz.com/edit/github-9csjsf?file=src/routes/index.tsx this should be it, but seems like stackblitz has a problem with router I've readjusted some things and used createResource in my repo, it works now, seems like createCachedResource was the problem @lxsmnsyc thank you for your time and help actually, isFetching is the problem
lxsmnsyc
lxsmnsyc•15mo ago
okay good to know, I'll look into solid-cache
aquarazorda
aquarazorda•15mo ago
const { data, isFetching }= useRouteData<typeof routeData>(); <Show when={data} fallback={<>Loading</>}> so if in when I'm using !isFetching() , I have this issue when I have data in when, then it works <Show when={data} fallback={<>Loading</>}> works <Show when={!isFetching()} fallback={<>Loading</>}> doesn't work
lxsmnsyc
lxsmnsyc•15mo ago
if you're relying on isFetching it wouldn't work, you need to call data first isFetching is only useful for transitioning data Hence why I wanted you to use Suspense on the accessing component
aquarazorda
aquarazorda•15mo ago
gotcha, <Show when={!data.loading} fallback={<>Loading</>}> this doesn't work as well. So if I have data wrapped with Suspense, I don't need this check, right? btw Solid cache is great, only thing that I'm missing is, invalidating with keys, are you planning to implement it?
lxsmnsyc
lxsmnsyc•15mo ago
yes, Suspense relies on the fact that data() is called first yeah I don't intend to. I'm planning to do this on a new data fetching library. But let's see if I'll revisit this concept
aquarazorda
aquarazorda•15mo ago
Thanks again and good luck!