How do you get createAsync to refetch or mutate?
I have a webpage where I get a list of items from a database. I want to take advantage of SolidStart's preloading and the other benefits of a createAsync based resource so I used it instead of createResource. Users can click a delete button next to each list item to delete it, and the list should update in response (possibly via an action). Now it occurs to me that the docs don't currently specify when, if or how createAsync based resources refetch data or if the data can be mutated (say by useSubmission to avoid a bunch of trips between client and server). Does anyone know how to do this?
8 Replies
I just wanted to add that my initial assumption was that using one of the helper functions to invalidate the cache of the query would cause the createAsync based resource to update the UI but I've tried using reload, revalidate, and redirect for good measure in the return of my action and it hasn't been working so far.
One thing that is sometimes overlooked is that the
query
takes a name
as the second argument. You need that name if you are going revalidate via a redirect
which often done at the end of an action that results in a route change but also needs to compel various query
s to refetch.
If the query
takes arguments those arguments act as a key to the cached result. So when revalidating it is essential to specify the matching key to force the refetch—that is what the key()
and keyFor()
methods are for.redirect - SolidDocs
Documentation for SolidJS, the signals-powered UI framework
action - SolidDocs
Documentation for SolidJS, the signals-powered UI framework
query - SolidDocs
Documentation for SolidJS, the signals-powered UI framework
GitHub
solid-router/src/types.ts at 3c214ce2ceb9b7d9d39d143229a8c6145e83e6...
A universal router for Solid inspired by Ember and React Router - solidjs/solid-router
1. Preload the query and render its data inside a route component using createAsync.
2. Revalidate the key of the query rendered in the route component. This ensures that the query data is refreshed when an action is executed.
The query functions like a GET method, while the action functions like a POST method.
Just use revalidate directly if you don’t need to navigate to another page.
Something like return revalidate(query.key).
data can be mutated (say by useSubmissionThe intent isn't mutation as such. Typically the
pending
signal of the latest submission is used to show an optimistic value (which could be one of the submission arguments) in favour of the stale remote value.
Once the submission is no longer pending
the query
will have updated and can be shown again as a fresh value.
https://stackblitz.com/edit/solidjs-templates-7u2yad?file=README.md
If you actually want to truly temporarily update a value then splice a createWritableMemo
into the reactive graph, that way you can override it until the next time the actual reactive source updates.
https://discord.com/channels/722131463138705510/1330302780250001449/1330366296956735582peerreynders
StackBlitz
solid.js action cache interplay - StackBlitz
A Solid TypeScript project based on @solidjs/router, solid-js, typescript, vite and vite-plugin-solid
Solid Primitives
A library of high-quality primitives that extend SolidJS reactivity
Thanks for the help everyone. The consensus seems to be that the helper functions like revalidate and reload should automatically cause the the createAsync based resource to refetch. However, this is not what I'm seeing. I did however find another solution. Consider the following code snippet
const refreshTable = useSubmission(delEntryAction);
let tableEntries = createAsync(() => { let data; if (refreshTable.result === undefined){ data = getInitFetch(props.apiURL, limit(), pageNum()); } else { data = refreshTable.result; } return data; }); Ends up that the function body within createAsync is a reactive context so calling a signal there will trigger a refetch. Thankfully useSubmission outputs a signal based entity, so when my action resolves and gets a result it reads it into the useSubmission resource which then retriggers the createAsync resource as a derived signal, refetching the data.
let tableEntries = createAsync(() => { let data; if (refreshTable.result === undefined){ data = getInitFetch(props.apiURL, limit(), pageNum()); } else { data = refreshTable.result; } return data; }); Ends up that the function body within createAsync is a reactive context so calling a signal there will trigger a refetch. Thankfully useSubmission outputs a signal based entity, so when my action resolves and gets a result it reads it into the useSubmission resource which then retriggers the createAsync resource as a derived signal, refetching the data.
However, this is not what I'm seeing.For that to work the actual fetch function has to be wrapped in a
query
.
An example I had from another topic:
https://playground.solidjs.com/anonymous/de1ecf9e-b57b-42cc-b3c0-39e7b6927ad6
And also by default action
s revalidate all active query
s. Given that you are already using an action
revalidation should “just work” provided the function used by createAsync
accesses the fetch result via a query
.
revalidate
version of the above without action
:
https://playground.solidjs.com/anonymous/ecfc76e8-3183-4298-8507-7aaae485025aSolid Playground
Quickly discover what the solid compiler will generate from your JSX template
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Thanks for your help again. I have been suspicious that I have been messing up the preload syntax somehow, so that what is preloaded is not connected to what I'm using in my createAsync resource. However, as I looked over my code to prepare a simplified example to get your opinion, I realized I had a "use server" directive at the top of the file I declared my queries in. That seem like a likely source for the problem I'm having and sure enough after removing it everything works as intend.
As it happens I also threw together an example with preload today:
https://discord.com/channels/722131463138705510/910635844119982080/1349086382081183815