Below are the official breaking changes and features for v3. If you have a feature request or idea, please use the Discussions tab to open a new discussion about that idea.
Global:
Query:
QueryCache:
ReactQueryCacheProvider
QueryObserver:
Query Config:
Would be nice to address this somehow in v3 https://github.com/tannerlinsley/react-query/discussions/669
@tannerlinsley is there any support for class components for react? not directly but rendering a functional component with query hooks into a class component.
For V3, I'd propose allowing extending the QueryCache class when calling makeQueryCache (or providing a custom cache).
Use case: I am writing test utilities that allow you to mock named queries and right now the QueryCache methods for getting/setting only work with exact query key matches but when testing, we want to support partial matching.
To handle this, I have to mutate the queryCache that comes back to override methods when it would be nicer to extend QueryCache instead.
class TestQueryCache extends QueryCache {
// override member methods as-needed
}
const testQueryCache = makeQueryCache(TestQueryCache);
// or queryCaches.push(testQueryCache) could also probably work
// but this leaks implementation details
At the crux of this I am looking for a way to intercept cache gets and sets, so any way to accomplish the same thing would work as well. 馃憤
@tannerlinsley
If there is something I can help with I would be glad to assist.
@kamranayub in the latest version the QueryCache class is exported and can be used to instantiate a query cache
Aw bummer I like how the global queryCache does not use Context. How will we access the queryCache in our custom hooks then? Or set the queryCache programmatically for fetch-as-you-render? Also I'm working on a lib that behaves like Zustand (global state) but uses regular hooks. I was excited by the prospect of being able to actually use the two libs together elegantly instead of just using them side-by-side.
Would there be any interest in allowing a zustand-like selector to subscribe to only a selected portion of the query's data? That way components could have granular control of re-renders.
Something like this:
// All data
const { data: { count, items, limit, offset} , isLoading, isSuccess, } = useQuery('items', () => fetch('/api/items'))
// Just the count
const { data: count, isLoading, isSuccess, } = useQuery('items', () => fetch('/api/items'), { select: s => s.count })
Would there be any interest in allowing a zustand-like
selector...
Oh looks like this may be something that could happen: https://github.com/tannerlinsley/react-query/pull/883#issuecomment-675889556
@timkindberg, the const queryCache = new QueryCache() that you make can still be a singleton, just like the currently exported queryCache global, and thus shouldn't change anything about how you can imperatively interact with the queryCache. It will just be import queryQuery from '../myQueryCache' instead of import { queryCache } from 'react-query'.
Yes we have discussed selectors a bit. We'll have to see how that conversation progresses.
@timkindberg best way to access a query cache in custom hooks is with useQueryCache.
Are there any particular recommendations that we should know about to use in place of usePaginatedQuery, or is it just as simple as start replacing it with useQuery and call it a day? Only other thing that comes to mind immediately is to do a prefetch for any pages with direct links on the screen.
Can we address #991 in V3?
Hi @tannerlinsley, is there any more context around these todo items? Particularly, I'd be interested to know why Remove usePaginatedQuery made it to this list. Thank you!
usePaginatedQuery can be replaced with a config option on useQuery. That's actually how it's implemented now (keepPreviousData):
Thank you @razh!
- [ ] Change
isFetchingtoisFetching()and do not store state
I documented an unnecessary render that is happening when the query first mounts and can theoretically know that it needs to rerender to set isFetching from false to true, since the cache is stale. You can see it in action in the sandbox below. Will this change solve this (minor) problem?
https://codesandbox.io/s/currying-dust-dom4u?file=/src/App.js
Edit: Maybe I misunderstood this change because it's under the QueryCache and not the Query section, but I am still curious about whether the above issue can be solved.
I forked your sandbox with V3 and it seems to resolve the issue: https://codesandbox.io/s/kind-cookies-6l56e
How can I test v3? As per Tanner's tweet npm install react-query@beta should do it but it's pulling v2.24.0 instead (_which matches what's published on npm_)
I'm using Next.js and try to upgrade v2.24.0, cacheTime: Infinity doesn't seem to work properly.
MyApp.getInitialProps = async () => {
await client.prefetchQuery(
'posts',
() => {
// return fetch()
},
{
cacheTime: Infinity,
},
);
}
Some where
const posts = client.getQueryData('posts');
Hi @nghiepit! Can you provide some more code and create an issue?
@boschni new https://github.com/tannerlinsley/react-query/issues/1140 issue created
It seems 2.40+ releases are already targeting the v3 changes. Consider fixing the release versions to avoid confusing people.
The breaking change that hit me was the removal of the default cache.
We鈥檙e aware. Working on a fix. At least they鈥檙e on the beta channel. If you鈥檇 like to submit a PR to help fix it, feel free.
Just an idea:
Have you ever considered (optionally, if configured so) to use browser cache as a cache for react-query? It would enable out-of-the-box PWA support. As much as I like the idea to use service worker for caching static resources, it would be nice to use single caching approach for data queries. It may enable instant reload of CSR (client side rendered) SPAs as long as data and resources are in cache.
Just an idea:
Have you ever considered (optionally, if configured so) to use browser cache as a cache for react-query? It would enable out-of-the-box PWA support. As much as I like the idea to use service worker for caching static resources, it would be nice to use single caching approach for data queries. It may enable instant reload of CSR (client side rendered) SPAs as long as data and resources are in cache.
We did this in our App and I would suggest avoiding it. Different browsers / user settings impose different limits on what and how much can be stored on the browser. Hitting those limits would cause exceptions at best and subtle unexpected behavior at worse
Looks like v3 is going to be about 10k(minified) larger than v2 according to https://bundlephobia.com/[email protected]
With gzip I realize it's only an extra 1kb, but it's still a hit to low-end mobile when keeping bundle size low is becoming harder. Is there a size target y'all are aiming for?
@greggb, we're always trying to keep good tabs on the size, since that's one of it's features when compared with apollo and other similar libraries. Even with the addition of the parsed 10kb, we're still well under what most other libraries are. For the future, if and when bundle size takes a giant leap, we're fully prepared to break out the library into separate bundles (much like the hydration api is now) and let users only import what they need.
@tannerlinsley Thanks Tanner. Reassuring to hear it's a priority for the library. 馃
Good point @greggb, there are some ways to mitigate this though. Created a proposal here: https://github.com/tannerlinsley/react-query/discussions/1164
If you need any help with the v3 work, I'd enjoy to contribute - I would just need a little guidance on where to start. :smile:
Imagine you have REST API client instances, you use to make requests, but in tests (or during development if API is not yet implemented...) you want to replace all clients with fake ones.
I would use react context for the use case but it would be nice to have something built in.
My proposal is:
It would be nice to have option to supply wrapper for every queryFn, configured at startup when creating QueryCache. The wrapper function can then supply additional arguments to queryFn.
There is option to provide default queryFn, but the use case I am looking for is not the same.
Imagine you have REST API client instances, you use to make requests, but in tests (or during development if API is not yet implemented...) you want to replace all clients with fake ones.
I would use react context for the use case but it would be nice to have something built in.
My proposal is:
It would be nice to have option to supply wrapper for every queryFn, configured at startup when creating QueryCache. The wrapper function can then supply additional arguments to queryFn.
There is option to provide default queryFn, but the use case I am looking for is not the same.
In my project I use msw to mock the whole API. It is useful to use in the test and also for prototyping when running in dev. There is the advantage of avoiding mocking any implementation in your code. This can be an option.
Imagine you have REST API client instances, you use to make requests, but in tests (or during development if API is not yet implemented...) you want to replace all clients with fake ones.
I would use react context for the use case but it would be nice to have something built in.
My proposal is:
It would be nice to have option to supply wrapper for every queryFn, configured at startup when creating QueryCache. The wrapper function can then supply additional arguments to queryFn.
There is option to provide default queryFn, but the use case I am looking for is not the same.In my project I use msw to mock the whole API. It is useful to use in the test and also for prototyping when running in dev. There is the advantage of avoiding mocking any implementation in your code. This can be an option.
Nice one, but there are other use cases where mocking solution of this sort is not sufficient. As I was going through API reference It came to me I can use queryFnParamsFilter to add extra argument (service container) to my queryFns. This is what I was looking for even thou it seems weird to add something in function called like that.
@timkindberg re: selectors. 馃憤 We have a wrapper factory we wrote for our lib-specific query implementation that actually uses Reselect so we actually hide data from react-query and instead return a select function:
import { useCurrentUser, selectAddress } from '@data/users';
const { select } = useCurrentUser();
const address = select(selectAddress);
I like the idea of this being built-in to react-query (or as an extension) because when you use a selector ideally you'd only want the hook to cause a re-render if that selected data has changed whereas right now it'll change when data changes.
all points seem to be checked, any planned date for official v3 release?
Hi there 馃憢, I'm wondering if it would make sense to allow the QueryFunction type to accept a second argument to enable typing the QueryFunctionContext, and in turn allow QueryFunctionContext to accept a second argument to enable typing its queryKey.
Take an example like the one from the Query Function Variables doc:
function Todos({ completed }) {
const result = useQuery(['todos', { status, page }], fetchTodoList)
}
function fetchTodoList({ queryKey }) {
const { status, page } = queryKey[1]
return new Promise()
}
In typescript I would define fetchTodoList as something like:
const fetchTodoList: QueryFunction<TodoListResponse> = ({ queryKey }) => { // ... }
However, accessing the variables with const { status, page } = queryKey[1] results in a type error.
I wish I could do something like this:
const fetchTodoList: QueryFunction<TodoListResponse, QueryFunctionContext<{status: string, page: number}>>
Does that make sense, or am I missing another way around this? Thanks for the great repo!
Hi @dougmacklin! Inline query functions are preferred, but I added the possibility to type the query key
Wow thanks for the quick addition @boschni!
When you say "inline function are preferred", do you mean it would be better to just do something like:
const result = useQuery(['todos', { status, page }], () => request(`/api/todos?status=${status}&page=${page}`))
and avoid extracting the query key altogether?
Np! Yeah either like that or create a function like fetchTodos(status, page) => request(...) and use that one instead of calling request directly but that is up to you :)
Is v3 better for new users?
Most of the problems seem to have been resolved, but when will it be officially released?
I have completely broken typing with v3 and can't get why. Eg, useQuery return value is infered as any and I don't recieve proper suggerstions for arguments. Ctrl+click on use query still shows some types in d.ts but can' get why it isn't applied.
Most helpful comment
Are there any particular recommendations that we should know about to use in place of
usePaginatedQuery, or is it just as simple as start replacing it withuseQueryand call it a day? Only other thing that comes to mind immediately is to do a prefetch for any pages with direct links on the screen.