Async Context and Store using route param
I'm sure the answer to this will be deceptively simple but I can't figure it out.
In my SolidStart project, a user navigates to a "project" by route, e.g. /project/foo.
The file is
/project[key].tsx
and using const params = useParams()
can retrieve params.key
perfectly.
The next step was:
This works great and I can then use <Suspend>
and friends and project data renders when available.
BUT as you can imagine, the loaded project data and operations on that data are needed deeply throughout the page.
To avoid prop drilling I want to make a Context
that provides a Store
to provide both the data and the operations.
At the top-level this reads fine:
That provider is drafted as below... I know it's not right but I don't know how to get the data returned by createAsync
to updated or set into the context:
I know that createAsyncStore
exists but I don't understand what it returns and how to use it in a context.
Any help most appreciated!8 Replies
You can see the WIP version of
makeProjectContext
below, and my confusion how to go from an empty placeholder store to the real data from the API:
Just declare your data fetching function in a separate file wrap the function in query and export it.
Now you can call this in any component with createAsync or createAsyncStore and solid will dedupe the requests thanks to query.
But doesn‘t trpc do that by default? It used Tanstack query under the hood. Which dedupes requests afaik.
query - Solid Docs
Documentation for SolidJS, the signals-powered UI framework
SolidStart also has a built in way for typesafe data fetching combining "use server" with query and optional preloading
https://docs.solidjs.com/solid-start/building-your-application/data-loading#data-loading-always-on-the-server
Data loading - Solid Docs
Documentation for SolidJS, the signals-powered UI framework
Thanks for the repy @Madaxen86 !
Re tRPC, it's a good point that I may not need that. I'd used that on a previous project and carried it over.
But ... putting that to the side, if I say that the async query function is just a
setTimout
followed by returning hard-coded data, I can't figure out how to get the result of that into the context.
A key point is that the data is held in a store and then manipulated by functions provided in the context, so I'm not concerned with deduping queries here.Example from the docs
Now you wrap this component in another to fetch the data and wrap you context component in Suspense and pass the initial value as a prop.
That’s should work.
Thanks for the detailed answer!
Here's where I've got to, which works but I'm really not sure about the use of memo:
I've noted that the
Suspense
doesn't work - if I put an artificial delay in the async call, nothing displays at all. I can live with it, but I don't really understand it.
Thanks for your comments so far. Any additional insights, particularly about <Suspense>
and the memo would be great.createMemo is "eager" which means it will execute before render. This means that you'll read the async signal outside of the Suspense boundary and your app will Suspend on the next "higher" Boudary. Show uses createMemo under the hood. So you can just remove that from contextValue to make Suspense work as expected.