Use derived stores with svelte-query 5
In the svelte-query 5 docs, it says you can pass a writable store for queryOptions like so:
I tested and it works great. However, I then tried passing a derived store, and get an error that it can't read the data from the derived store (it says my queryKey and queryFn are empty, even though if I subscribe to the derived store I can see they are populated).
Does svelte-query 5 not support derived stores for query options?
36 Replies
ambitious-aqua•3y ago
Can you provide an example? Also, shouldn't the queryOptions store be accessed as $queryOptions?
extended-salmonOP•3y ago
Yes I will provide an example. In the docs online, it does not show the queryOptions being passed with a $
Hm, trying to put together an example in Codesandbox but I can't even get a basic QueryClientProvider working there, it is throwing an App constructor error? https://codesandbox.io/s/weathered-feather-8v8nvf?file=/App.svelte @Raytuzio can you let me know what I'm doing wrong here?
ambitious-aqua•3y ago
Svelte stores need to be accessed with $ - the docs haven't been updated yet to demonstrate how to use this feature, but it's the same as the rest of svelte.
That doesn't look like how you build a vite app with svelte. How did you generate this template?
ambitious-aqua•3y ago
You can look at this example: https://github.com/TanStack/query/tree/main/examples/svelte/simple
GitHub
query/examples/svelte/simple at main · TanStack/query
🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query. - query/examples/svelte/simple at main ·...
extended-salmonOP•3y ago
This is a typical Codesandbox svelte template that works perfectly fine until svelte-query 5 is introduced...
extended-salmonOP•3y ago
No, in svelte-query 5 you do not pass the store with a $ sign, the type for CreateBaseQuery options explicilty states that you can pass it a Writable, which would be a store that hasn't been unwrapped. Hence the ability to get reactivity. Which means the docs listed here are correct https://tanstack.com/query/v5/docs/svelte/reactivity
CreateBaseQuery options type:
https://github.com/TanStack/query/blob/alpha/packages/svelte-query/src/types.ts#L19-L27
Reactivity | TanStack Query Docs
Svelte uses a compiler to build your code which optimises rendering. By default, variables will run once, unless they are referenced in your markup. To be able to react to changes in options you need to use stores.
In the below example, the refetchInterval option is set from the variable intervalMs, which is edited by the input field. However,...
GitHub
query/packages/svelte-query/src/types.ts at alpha · TanStack/query
🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query. - query/packages/svelte-query/src/types....
extended-salmonOP•3y ago
In CreateBaseQuery you can see that it expects options to either be a writable or it converts it to a writable https://github.com/TanStack/query/blob/alpha/packages/svelte-query/src/createBaseQuery.ts#L27
GitHub
query/packages/svelte-query/src/createBaseQuery.ts at alpha · TanSt...
🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query. - query/packages/svelte-query/src/create...
ambitious-aqua•3y ago
Oh I see, sorry, I haven't used it myself.
So it works with svelte-query v4?
extended-salmonOP•3y ago
Nah, it doesnt work with v4 either. And I can't load v4 in a svelte repl either, I get a "process is not defined" error.
Trying to figure out best way to get you some reproducible code...
extended-salmonOP•3y ago
Ok, I've got it working @Raytuzio
Here is example 1, using svelte-query v5 with a writable store for the options like the documentation says: https://svelte.dev/repl/7d299dce4d9a4b6ba590d6707f383d62?version=4.0.2
And that works as expected!
Svelte-queryv5 example 1 • REPL • Svelte
Cybernetically enhanced web apps
extended-salmonOP•3y ago
Now here is another version of that example where I try to use a derived store for queryOptions. It does not work at all - svelte query doesn't try to fetch anything. But I can see by logging in the console that my derived store queryOptions looks just like my options did in example 1 https://svelte.dev/repl/ee90c13684af4672a19661e9e9021da3?version=4.0.2
Svelte-queryv5 example 2 derived • REPL • Svelte
Cybernetically enhanced web apps
ambitious-aqua•3y ago
Ahh I see - I love this example!
You're right, it doesn't even attempt to fetch
I'll have a look into it! I'd also appreciate it if you could create an issue on the github repo here: https://github.com/TanStack/query/issues
extended-salmonOP•3y ago
Bug report: https://github.com/TanStack/query/issues/5668
GitHub
[Alpha] svelte-query v5 doesn't accept derived stores for options ·...
Describe the bug In the documentation for svelte-query v5, it is suggested that you can provide stores for queryOptions in order to make reactive queries: https://tanstack.com/query/v5/docs/svelte/...
ambitious-aqua•3y ago
Hi @speros , just want to check that everything works with the new update?
extended-salmonOP•3y ago
Yes it works! Awesome, thank you!
ambitious-aqua•3y ago
No worries! I've definitely under-utilised derived stores in my own projects but they seem incredibly useful
@speros I identified another bug now that the queries can be truly reactive - if you were using staleTime and changes didn't react properly before, they should work now: https://github.com/TanStack/query/pull/5682
Also if you don't need to access your derived store anywhere else, you can just do this:
extended-salmonOP•3y ago
Awesome!
Do all these subscriptions created internally by
createQuery
get cleaned up when that query produced is no longer being subscribed to? Might be something worth double checkingambitious-aqua•3y ago
Good point, I will check
It should be fine based on the svelte docs 🙂
genetic-orange•3y ago
this is probably not possible in v4 ?
ambitious-aqua•3y ago
Sorry, it's not possible - you can achieve something similar (but not as good) with these instructions: https://tanstack.com/query/v4/docs/svelte/reactivity
Reactivity | TanStack Query Docs
Svelte uses a compiler to build your code which optimises rendering. By default, variables will run once, unless they are referenced in your markup. To make a different variable or function reactive, you need to use reactive declarations. This also applies to Svelte Query.
In the below example, the refetchInterval option is set from the variab...
ambitious-aqua•3y ago
Or just use v5 alpha! 🙂
robust-apricot•3y ago
Guys @Raytuzio @speros when using derived with createQuery, there is chance, that you need import some writable store from .svelte to .ts file? Haven't you had any problems with TS doing so? Im having hard time with
Module '"*.svelte"' has no exported member
when importing from .svelte to .ts file. Maybe you have any workarounds for this?ambitious-aqua•3y ago
@kaszakukus I'm not quite sure what you mean - you shouldn't need to do that. Can you give an example?
robust-apricot•3y ago
I have this in
createAppQuery.ts
and dataRefetchIntervalS is store imported from <script context="module"></script> .svelte file
because dataRefetchIntervalS is imported from .svelte to .ts file Im getting: error TS2614: Module '".svelte"' has no exported member 'dataRefetchIntervalS'. Did you mean to use 'import dataRefetchIntervalS from ".svelte"' instead?
@Raytuzio thought its very common case. I am missing something?ambitious-aqua•3y ago
Does dataRefetchIntervalS need to be in a svelte file? Is it meant to represent a sharable store or a store specific to that svelte file?
robust-apricot•3y ago
Basically its kinda sharable store - needed while creating query by
createQuery
, but its also connected with .svelte file which holds logic and UI to enable setting interval. I think the best workaround is to keep my function createAppQuery in .svelte file inside context="module" script, or as you suggest to move writable store to some .ts fileextended-salmonOP•3y ago
Yes, I'm not super familiar with how svelte modules work but I don't believe there is any support for importing from them into TS files. Normally I would export and shared store from a TS file
sensitive-blue•3y ago
unfortunately types don't seem to fully work at the moment when using derived stores in queries/mutations: https://discord.com/channels/719702312431386674/1136157186796556438
sunny-green•3y ago
Hey @Raytuzio! I noticed that if my derived store returns the the same queryKey, but updated the
queryFn
, the underlying queryFn
is never changed. Is that intended?
If so, should I be including the parameter that my derived store is using in the key?
Ah I see. Is there a recommended way to share CreateQueryResult
objects between components? For example, I have a global query that's being executed in a parent component, and I want to subscribe to that same query from a child component.
Ohhhh I think it’s because I was expecting that changing the query function would automatically invalidate and replace the query data too… is there any way to return an option from the derived update which would clear the query? Or I guess I would have to trigger it manually for each query?ambitious-aqua•3y ago
Hi @ap , that sort of behaviour doesn't sound like it should work - it won't try to refetch data if the same query key is used (this isn't a svelte-specific thing). Do you want to share your code so we can help find a solution?
sunny-green•3y ago
Sure here's the gist of it --
Basically, in the Child component, it seems to me that I'm not fetching the query correctly -- if the query resolves in the parent immediately, the child component never sees the
{}
resolve, and when the username
changes, the Child component never sees the updated query, as the updated queryFn
is never actually run.
I'm sure I'm doing something wrong as I've never used react-query, or svelte-query before, but would be helpful to know exactly what (only have a faint idea)
I mean -- I can see how the "a solution" would be to use a queryKey of ["user", "info", $username]
, and then use that in the Child component query as well, but I'm not sure if that is the "correct solution"ambitious-aqua•3y ago
If you change your queryKey to
queryKey: ["user","info", $username]
that would work for +layout.svelte. Is there a reason why username needs to start out undefined?
I have to say I've never seen a conditional queryFn like that - if you're using SSR you might want to use a +layout.ts file then throw an error if username is undefined? However I don't know what your app looks like beyond this snippet.sunny-green•3y ago
I'm basically using
undefined
as equivalent to a logged-out view in my app, so an empty object for user info is handled during rendering certain information panels.
Yeah -- I guessed as much regarding the query key and so on. Makes sense to me why that would be the preferred approach. Just wrapping my head around it all. Tysm!ambitious-aqua•3y ago
No worries! Any time you expect a query to return data from a different endpoint/resource/whatever, it needs its own key
sunny-green•3y ago
Second issue: If I create the query, but don't use the returned store in the
+layout.svelte
, then the query never seems to resolve in the Child component. If I add a reader to the original query in layout, such as console.log($query.status)
, then it resolves.
I can guess why this is, but what's the suggested workaround? Are queries meant to be kept in a global js/ts file separate from the component?ambitious-aqua•3y ago
If you don't need to use the user query in your +layout.svelte, you can remove it from there! You can just use the query directly in the component you actually want it in, such as your Child.svelte component. I would've expected it to still resolve despite this, but I don't know the full context of your app.