-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
[svelte] keepPreviousData not working #4851
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Interesting - I think solid-query gets around this by defining the inline options object as reactive, while in svelte you need to define the whole line as reactive. I wonder if defining the options before calling createQuery fixes this issue? So it would look like |
I tried that and it didn't work for me. I had a deeper look into this and, among other things, checked how tanstack/table handles it and they seem to use a writable store for the entire options object. I think this would also be a good idea for svelte-query. It would look something like this: const options = writable({
queryKey: ['test', [1]],
queryFn: async ({ queryKey }) => {
await sleep(100)
return queryKey[1]
},
keepPreviousData: true,
})
const query = createQuery(options) Within svelte files you can then simply update the options like so: $options.queryKey[1] = [1, 2] And outside of svelte files: options.update((o) => ({ ...o, queryKey: ['test', [1, 2]] })) If you do not need the reactivity you can still use a regular options object. I made a PoC with a test that was failing before and working with these changes. I do not know query-core well though, so I'm not sure all changes are completely correct. You can check this here: main...chrislcs:query:main |
This looks great :) The only bit that I'm a bit concerned about is forcing the types on parseQueryArgs, as this would also need to be done for the other functions that use createBaseQuery and have more complex types. However in v5, there will be no passQueryArgs, so maybe this could be a v5 feature - do you want to submit a PR into the v5 branch? EDIT: I've also just checked this never worked with the old package either. |
Yeah forcing the types isn't pretty, was just meant as a PoC. With the current implementation of if (!isQueryKey(arg1)) {
return arg1 as TOptions
}
if (typeof arg2 === 'function') {
return { ...arg3, queryKey: arg1, queryFn: arg2 } as TOptions
}
return { ...arg2, queryKey: arg1 } as TOptions
EDIT: Scratch that. Now that I thought about it more, it wouldn't work if the writeableOptions are not the first argument. We'd need to update the writable with the other arguments if it isn't passed as the first argument. Still not too difficult, but more substantial. Worth it to do that or just go for v5? I can make a PR tomorrow 👍 |
I think probably just go for v5, thanks for figuring this out! Also I doubt this would fix the problem since createQuery still gets re-run, but keepPreviousData will be merged into placeholderData in v5: #4715 |
Sorry for the sudden lack of activity from my side, I caught the flu and was unable to work on this for a while. I hope to make the PR soon. |
How would you make the query reactive to external variables (as opposed to user events such as the By following the new reactivity documentation the only thing that works for me is the following, but that doesn't feel very intuitive: const ids = $page.url.searchParams.getAll(name)
const queryOptions = writable({
queryKey: ['reactive', ...ids],
queryFn() {
return fetchWithIds(ids)
},
placeholderData: keepPreviousData,
})
const query = createQuery(queryOptions)
$: {
const nextIds = $page.url.searchParams.getAll(name)
$queryOptions = {
queryKey: ['reactive', ...nextIds],
queryFn() {
return fetchWithIds(nextIds)
},
placeholderData: keepPreviousData,
}
} Am I missing something ? Thanks ! |
You should use the provided queryKey in the query function. This way you do not have to update the query function. Something like this (quickly wrote this, not tested): const ids = $page.url.searchParams.getAll(name)
const queryOptions = writable({
queryKey: ['reactive', ids],
queryFn: ({ queryKey }) => fetchWithIds(queryKey[1]),
placeholderData: keepPreviousData,
})
const query = createQuery(queryOptions)
$: {
const nextIds = $page.url.searchParams.getAll(name).map(Number)
$queryOptions.queryKey[1] = nextIds
} |
While this is indeed a bit shorter, it still doesn't feel as right as leveraging reactive statements Nonetheless, this now raises the question of typings since we don't benefit from autocompletion in
Any idea of to make it work seamlessly with TS ? |
I either do not understand what you mean by it not feeling right, or I do not agree. Anyhow, you can type the writable options as const queryOptions: Writable<CreateQueryOptions> = writable({
queryKey: ['reactive', ids],
queryFn: ({ queryKey }) => fetchWithIds(queryKey[1]),
placeholderData: keepPreviousData,
}) Or with typescript 4.9 or higher you might be able to do this for narrower types (didn't test it tho): const queryOptions = writable({
queryKey: ['reactive', ids],
queryFn: ({ queryKey }) => fetchWithIds(queryKey[1]),
placeholderData: keepPreviousData,
}) satisfies Writable<CreateQueryOptions> |
I'm running into the same issue on 4.29.11 and v5.0.0-alpha.56 even when I use the writable store for my query options |
It's only available on the alpha version. The main difference is that |
Sorry snuck an edit in right before your commented didn't think I'd get a reply so fast 😅 I tried on the alpha release and still am getting the issue with the query state changing to loading when fetching the same query with a new query key. Also now I'm getting a type error that |
They changed the API for this on the alpha version. You should import the import { createQuery, keepPreviousData } from '@tanstack/svelte-query'
createQuery({
placeholderData: keepPreviousData
}) Some of the previous replies demonstrated this new usage: |
@tmarnet you can now use derived stores with createQuery in v5 alpha - you can see an example here: https://tanstack.com/query/v5/docs/svelte/reactivity |
import { createQuery, keepPreviousData } from '@tanstack/svelte-query';
// "@tanstack/svelte-query": "5.0.0-beta.20"
let post: string;
$: query = createQuery({
queryKey: [post],
queryFn: () => getPosts(post),
placeholderData: keepPreviousData
}); Doesn't work for me still, shows undefined on post updates - is it because query is recreated on every post change? What's the recommended pattern here? Turn |
Describe the bug
The
keepPreviousData
options does not seem to work in the svelte-query. Even when set to true the data is empty until the new query is done.I made the query reactive using the documentation here: https://tanstack.com/query/v4/docs/svelte/reactivity
I think it is because the current syntax will rerun the
createQuery
method and create a new query object each time any used variable changes, instead of subscribing to change within the already created query object, but I do not know enough about the inner workings of query-core and svelte-query to know if this is indeed an issue.Your minimal, reproducible example
https://codesandbox.io/s/nifty-cloud-pxwjho?file=/App.svelte
Steps to reproduce
Expected behavior
As a user, I expected the previous data be visible in the DOM during fetching of the updated data
How often does this bug happen?
Every time
Screenshots or Videos
No response
Platform
TanStack Query version
4.22.3
TypeScript version
4.9.4
Additional context
No response
The text was updated successfully, but these errors were encountered: