How Do I Update The createAsync() Signal?
I've been trying to use
cache()
, load()
, and createAsync()
because this pattern appears to be the preferred method for fetching data with SolidStart. Unfortunately, I can't figure out how to update the createAsync()
signal.
When using createStore()
you get access to a getter and a setter:
But when using createAsync()
I only get access to a getter.
How can I update the getter "notes" when using createAsync()
?27 Replies
Warning this is probably a hack.
I solved it at the cache level. I associated a synchronization data object with the cache. Update the synchronization data then kick off revalidation for the cache point and it pushes out the fresh data
In my case it was easy because that was how the cache got its value but if you are blending fetching and mutating … you really should be doing optimistic updates with
useSubmission
.
Examplepeerreynders
StackBlitz
solid.js action cache interplay - StackBlitz
A Solid TypeScript project based on @solidjs/router, solid-js, typescript, vite and vite-plugin-solid
GitHub
GitHub - solidjs/solid-router: A universal router for Solid inspire...
A universal router for Solid inspired by Ember and React Router - solidjs/solid-router
Thank you. This seems a lot more involved than using createStore().
Two questions:
1. How much more performant is the cache method vs the store method? I'm wondering if it's worth all of the extra set up.
2. Ryan mentiond that we can use
cache.set()
to mutate data in this post :https://github.com/solidjs/solid-start/discussions/1225#discussioncomment-8806242 Could cache.set()
work in this case?GitHub
Mutate cache data · solidjs solid-start · Discussion #1225
Hi! Is there a pattern to optimistic mutate data loaded with cache and createAsync ? Similar to mutate in createResource. Would be great to be able to preload data on the server with use server in ...
I've got a different pattern working pretty well now.
For the record, I'm doing all of this to use realtime updates from supabase.
This pattern allows me to create a cache and load everything on the server while still taking advantage of realtime updates using a store.
Here's how it works.
Get the notes on the server
Call load() to take effect of loading the data on hover.
Create a reactive notes value with
createAsync()
Pass notes to a child component
<Notes notes={notes} />
Inside of <Notes />
load the data into a store and react to any realtime updates.
This seems like a pretty good solution. Would you agree?I'm wondering if it's worth all of the extra set up.The elephant in the room is: what is the context you are using this in. Using
cache.set()
is flawed given that it destroys the value known to have been valid in the past which for all we know is how the server is still viewing the world.
Start supports single flight mutations so that an action can immediately return the redirect result that would normally require a followup request by the browser to the URL listed in the location header of a 302 response-so if your connections are fast enough there is probably no need to leverage useSubmission
.
useSubmission
exists to bridge that period of uncertainty where the client knows what the result should be but has not yet received agreement from the server-and it operates in a fashion that does not destroy values that are known to have been previously valid.
Setters on signals and stores are great for local ephemeral state; i.e. state that would simply disappear (or be re-derived) once you actually reload the page from the server.
But the cache/createAsync/useAction/useSubmission mechanism was created for non-ephemeral state; the type of things that both the server and the client have to agree on.GitHub
Release v0.6.0 - Take Flight · solidjs/solid-start
Listening carefully to the feedback and reflecting on the second month of beta 2 we have prepared this release which improves on a lot of the usability around Start itself. This is less about featu...
To be honest I know people do it but every time I see a setter inside a
createEffect
it sets my teeth on edge-to me it screams design issue.
And I suspect the core of that is this:
use realtime updates from supabase.
Haha
How fast does supabase come back with updates?
Very fast.
Pretty much as soon as I click the button.
Moving the setter outside of
createEffect
gives me an empty screen because notes hasn't populated when the componenet loads. That's why I placed it inside of createEffect()
.
I'd redesign the cache handling. Have the update write to a synchronization area and then invalidate the cache so that the fetch function picks the up to date values.
Wouldn't each call the fetch function initiate another network request to Supabase?
Example: SSE events show up whenever they feel like it. There is no "fetch".
The most up-to-date state is held inside a simple (singleton) class:
MessageHistory
.
HistoryState augments that class with reset
and shunt
functions which wrap cache invalidations.
Within the context value that state and the cache points are bound together via their respective names.
Now whenever a new set of messages comes in shunt
is called:
- MessageHistory
is updated
- Then the appropriate cache invalidations are triggered causing the cache points to read in the updated data from MessageHistory
and pushing them onto the respective createAsync
(Store
).GitHub
solid-start-sse-chat/src/components/history-context/index.tsx at d2...
Basic Chat demonstration with server-sent events (SSE) - peerreynders/solid-start-sse-chat
GitHub
solid-start-sse-chat/src/components/history-context/message-history...
Basic Chat demonstration with server-sent events (SSE) - peerreynders/solid-start-sse-chat
Discord
Discord - A New Way to Chat with Friends & Communities
Discord is the easiest way to communicate over voice, video, and text. Chat, hang out, and stay close with your friends and communities.
Impressive work!
Seemed the right thing to do at the time.
I accomplished this in a similar way as Chris here over for handling a websocket. It definitely feels kinda hacky
https://github.com/brenelz/solid-poll/blob/main/src/routes/poll/%5Bid%5D.tsx#L23
GitHub
solid-poll/src/routes/poll/[id].tsx at main · brenelz/solid-poll
Contribute to brenelz/solid-poll development by creating an account on GitHub.
Yes, nearly identical. Thanks for weighing in @brenelz
how do we handle error with createAsync ?
I think that depends on the code inside of your cache.
If you are using fetch, I'd return any errors and handle them when calling createAsync().
I'm using Supabase. In my case, I check for the existence of
notes()
to handle errors.
So we need to wrap it with the error boundary?
It’s an option, but I don’t think that’s needed. I’m not doing it here.
If that is so, then when the error boundary catches the error, how would we have a button to retry ? It doesn't seem to work when using the revalidate function when the error caught
It seems like the error boundary was no longer there after it caught the error
Then when calling revalidate again it said uncaught errror
maybe try: to wrap/extend your fetched data with hasError. So if hasError is true you can display the button to retry. I think caching is still a problem though, since the build-in caching mechanism does not know that an error has happened and caches it instead. So I guess you have to build your own caching mechanism?
I expected the createAsync to be createResouce with cache, but turns out they didn't include the error state like what createResouce does
they didn't include the error state like what createResouce doesFrom the docs
Sounds to me that the expectation is that you will pick up the error in thedata.error
tells you if the request has errored out; if so, it contains the error thrown by the fetcher. (Note: if you anticipate errors, you may want to wrapcreateResource
in anErrorBoundary
.)
ErrorBoundary
anyway.
Another alternative is to just return the union (or tuple) of result and error from the cache
fn
- splitting state after the createAsync
.
Keep in mind SolidJS always focused on “primitives with which mechanisms can be built”.i wonder why createAsync implementation does not return the resource tho, it return the data instead
The way I see it:
createResource
was Ryan's first crack at an async-to-sync-reactive primitive. Once he widened his scope to SSR and ultimately fullstack he realized that createResource
wasn't actually a primitive.
In terms of fullstack composability useAction
/cache
/createAsync
were better building blocks.
The fact that createResource
appears inside of createAsync
right now is temporary until SolidJS 2.0. At that point createAsync
et al. will move into Solid core with implementations entirely decoupled from createResource
.that aims to serve as stand-in for a future primitive we intend to bring to Solid core in 2.0.https://github.com/solidjs/solid-router?tab=readme-ov-file#createasync
GitHub
GitHub - solidjs/solid-router: A universal router for Solid inspire...
A universal router for Solid inspired by Ember and React Router - solidjs/solid-router