[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?
this is the client side, which doesn't log fetched data when reloading.
this is the server side
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
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:
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:
Finally, on the client side, you need to hydrate your app with the data received from the server:
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.
there's no such thing as
runServerEffects
tbf the question isn't quite clear@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.
by refresh I assume you meant page reload/initial page load?
Yes, exactly. Sorry, English isn't my first language.
hmmm, okay, do you have some repro for this? or a video of the said behavior
hmmm okay thank you. What's your SSR mode currently? Sync, Async or Stream?
you can check out entry-server
ah, it's async
@lxsmnsyc just checked, it only works correctly when using renderSync
yeah it would if it was Sync
maybe a bug with async
same thing happens with stream
gotcha, will continue with sync for now. Thanks for your time and sorry for disturbing
Time to mention @ryansolid
when that promise resolves, whole page gets destroyed @lxsmnsyc
I guess I’m out of luck here 😬
what happens if you add Suspense to the component that reads data
and try removing the
createEffect
@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
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
So should I wrap <FileRoutes /> with Suspense?
That's what you meant?
just tested, it doesn't work
No, just the component that reads
data
e.g.
Gotcha, I'm reading data with routeData, that's what confused me, checking.
then wrap it around the element that reads from
useRouteData
interesting, now I see an error, instead of whole page going blank
and that data is undefined seems like
now promise resolves, I don't see that it's loading anymore
but data is undefined
resources are always undefined initially, I guess you're trying to access some property
that causes some render error
like
where in reality it is
that's just my assumption
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
without a repro I cannot really say the exact issue
but I see that it's being fetched and there's a value
I'll push it, need couple of minutes, thanks for your help!
you didn't mention you were using
createCachedResource
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.
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
should I create a plain solid-start repo and reproduce the issue there?
yes
basic reproduction please, at least only solid-start and solid-js
@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 problemokay good to know, I'll look into solid-cache
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 workif 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 componentgotcha,
<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?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 conceptThanks again and good luck!