Skip to content
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

v4 alpha #3060

Merged
merged 30 commits into from
Dec 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ad73004
feat(hydration): remove hydration package (#2936)
TkDodo Nov 13, 2021
e892557
V4: streamline cancel refetch (#2937)
TkDodo Nov 13, 2021
56598fb
feat: better query filters (#2938)
TkDodo Nov 14, 2021
b9a26f2
Merge remote-tracking branch 'react-query/master' into v4
TkDodo Nov 17, 2021
1f6ac11
fix: rename react directory to reactjs (#2884)
EddyVinck Nov 17, 2021
d1a7520
Merge remote-tracking branch 'react-query/master' into v4
TkDodo Nov 17, 2021
ac1eefd
feat: mutation cache duration (#2963)
TkDodo Nov 17, 2021
fa12391
refactor(persistQueryClient): Make persistQueryClient stable (#2961)
prateek3255 Nov 18, 2021
7a95ea6
Merge remote-tracking branch 'react-query/master' into v4
TkDodo Nov 18, 2021
a090fe5
2964 changes to on success callback (#2969)
TkDodo Nov 19, 2021
2624c42
2919 query key array (#2988)
TkDodo Nov 19, 2021
67b9a9b
Merge remote-tracking branch 'react-query/master' into v4
TkDodo Nov 20, 2021
5b464da
feat(QueryObserver): track queries as default (#2987)
babycourageous Nov 20, 2021
a701340
refactor: Remove deprecated promise cancel (#2996)
prateek3255 Nov 22, 2021
1226d8c
Merge remote-tracking branch 'react-query/master' into v4
TkDodo Nov 22, 2021
adcd99a
Merge remote-tracking branch 'react-query/master' into v4
TkDodo Nov 22, 2021
26949e5
Merge remote-tracking branch 'react-query/master' into v4
TkDodo Nov 26, 2021
b12bc2c
remove test that doesn't make sense anymore - we don't allow differen…
TkDodo Nov 26, 2021
fb13a05
Merge remote-tracking branch 'react-query/master' into v4
TkDodo Nov 28, 2021
bc116d3
2927 offline queries (#3006)
TkDodo Dec 1, 2021
670dec8
Merge remote-tracking branch 'react-query/master' into v4
TkDodo Dec 2, 2021
993b906
Merge remote-tracking branch 'react-query/master' into v4
TkDodo Dec 3, 2021
4b75108
refactor(queryClient): remove undocumented methods
TkDodo Dec 3, 2021
f804b15
fix: offline mutations fixes (#3051)
TkDodo Dec 4, 2021
6985a49
examples: fix query keys in basic examples
TkDodo Dec 4, 2021
0e5aaed
Merge remote-tracking branch 'react-query/master' into v4
TkDodo Dec 5, 2021
bd0f87c
fix(useMutation): make sure cacheCallbacks are always called
TkDodo Dec 5, 2021
bb1443c
Feature/cachetime zero (#3054)
TkDodo Dec 6, 2021
0e1bb92
add publishing capabilities for alpha branch
TkDodo Dec 6, 2021
217ee3a
fix(queryFilters): fetchStatus to queryFilters (#3061)
TkDodo Dec 6, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/test-and-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- 'master'
- 'next'
- 'alpha'
- 'beta'
- '1.x'
- '2.x'
Expand Down Expand Up @@ -36,7 +37,7 @@ jobs:
name: 'Publish Module to NPM'
needs: test
# publish only when merged in master on original repo, not on PR
if: github.repository == 'tannerlinsley/react-query' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/next' || github.ref == 'refs/heads/beta' || github.ref == 'refs/heads/1.x' || github.ref == 'refs/heads/2.x')
if: github.repository == 'tannerlinsley/react-query' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/next' || github.ref == 'refs/heads/alpha' || github.ref == 'refs/heads/beta' || github.ref == 'refs/heads/1.x' || github.ref == 'refs/heads/2.x')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand Down
6 changes: 6 additions & 0 deletions createAsyncStoragePersister/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"internal": true,
"main": "../lib/createAsyncStoragePersister/index.js",
"module": "../es/createAsyncStoragePersister/index.js",
"types": "../types/createAsyncStoragePersister/index.d.ts"
}
6 changes: 0 additions & 6 deletions createAsyncStoragePersistor-experimental/package.json

This file was deleted.

6 changes: 6 additions & 0 deletions createWebStoragePersister/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"internal": true,
"main": "../lib/createWebStoragePersister/index.js",
"module": "../es/createWebStoragePersister/index.js",
"types": "../types/createWebStoragePersister/index.d.ts"
}
6 changes: 0 additions & 6 deletions createWebStoragePersistor-experimental/package.json

This file was deleted.

26 changes: 18 additions & 8 deletions docs/src/manifests/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@
"path": "/guides/query-functions",
"editUrl": "/guides/query-functions.md"
},
{
"title": "Network Mode",
"path": "/guides/network-mode",
"editUrl": "/guides/network-mode.md"
},
{
"title": "Parallel Queries",
"path": "/guides/parallel-queries",
Expand Down Expand Up @@ -204,6 +209,11 @@
"title": "Migrating to React Query 3",
"path": "/guides/migrating-to-react-query-3",
"editUrl": "/guides/migrating-to-react-query-3.md"
},
{
"title": "Migrating to React Query 4",
"path": "/guides/migrating-to-react-query-4",
"editUrl": "/guides/migrating-to-react-query-4.md"
}
]
},
Expand Down Expand Up @@ -314,19 +324,19 @@
"heading": true,
"routes": [
{
"title": "persistQueryClient (Experimental)",
"title": "persistQueryClient",
"path": "/plugins/persistQueryClient",
"editUrl": "/plugins/persistQueryClient.md"
},
{
"title": "createWebStoragePersistor (Experimental)",
"path": "/plugins/createWebStoragePersistor",
"editUrl": "/plugins/createWebStoragePersistor.md"
"title": "createWebStoragePersister",
"path": "/plugins/createWebStoragePersister",
"editUrl": "/plugins/createWebStoragePersister.md"
},
{
"title": "createAsyncStoragePersistor (Experimental)",
"path": "/plugins/createAsyncStoragePersistor",
"editUrl": "/plugins/createAsyncStoragePersistor.md"
"title": "createAsyncStoragePersister",
"path": "/plugins/createAsyncStoragePersister",
"editUrl": "/plugins/createAsyncStoragePersister.md"
},
{
"title": "broadcastQueryClient (Experimental)",
Expand Down Expand Up @@ -442,4 +452,4 @@
]
}
]
}
}
2 changes: 1 addition & 1 deletion docs/src/pages/comparison.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Feature/Capability Key:

> **<sup>1</sup> Lagged Query Data** - React Query provides a way to continue to see an existing query's data while the next query loads (similar to the same UX that suspense will soon provide natively). This is extremely important when writing pagination UIs or infinite loading UIs where you do not want to show a hard loading state whenever a new query is requested. Other libraries do not have this capability and render a hard loading state for the new query (unless it has been prefetched), while the new query loads.

> **<sup>2</sup> Render Optimization** - React Query has excellent rendering performance. It will only re-render your components when a query is updated. For example because it has new data, or to indicate it is fetching. React Query also batches updates together to make sure your application only re-renders once when multiple components are using the same query. If you are only interested in the `data` or `error` properties, you can reduce the number of renders even more by setting `notifyOnChangeProps` to `['data', 'error']`. Set `notifyOnChangeProps: 'tracked'` to automatically track which fields are accessed and only re-render if one of them changes.
> **<sup>2</sup> Render Optimization** - React Query has excellent rendering performance. By default, it will automatically track which fields are accessed and only re-render if one of them changes. If you would like to opt-out of this optimization, setting `notifyOnChangeProps` to `'all'` will re-render your components whenever the query is updated. For example because it has new data, or to indicate it is fetching. React Query also batches updates together to make sure your application only re-renders once when multiple components are using the same query. If you are only interested in the `data` or `error` properties, you can reduce the number of renders even more by setting `notifyOnChangeProps` to `['data', 'error']`.

> **<sup>3</sup> Partial query matching** - Because React Query uses deterministic query key serialization, this allows you to manipulate variable groups of queries without having to know each individual query-key that you want to match, eg. you can refetch every query that starts with `todos` in its key, regardless of variables, or you can target specific queries with (or without) variables or nested properties, and even use a filter function to only match queries that pass your specific conditions.

Expand Down
14 changes: 7 additions & 7 deletions docs/src/pages/guides/caching.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ This caching example illustrates the story and lifecycle of:

Let's assume we are using the default `cacheTime` of **5 minutes** and the default `staleTime` of `0`.

- A new instance of `useQuery('todos', fetchTodos)` mounts.
- A new instance of `useQuery(['todos'], fetchTodos)` mounts.
- Since no other queries have been made with this query + variable combination, this query will show a hard loading state and make a network request to fetch the data.
- It will then cache the data using `'todos'` and `fetchTodos` as the unique identifiers for that cache.
- It will then cache the data using `['todos']` as the unique identifiers for that cache.
- The hook will mark itself as stale after the configured `staleTime` (defaults to `0`, or immediately).
- A second instance of `useQuery('todos', fetchTodos)` mounts elsewhere.
- A second instance of `useQuery(['todos'], fetchTodos)` mounts elsewhere.
- Because this exact data exists in the cache from the first instance of this query, that data is immediately returned from the cache.
- A background refetch is triggered for both queries (but only one request), since a new instance appeared on screen.
- Both instances are updated with the new data if the fetch is successful
- Both instances of the `useQuery('todos', fetchTodos)` query are unmounted and no longer in use.
- Both instances of the `useQuery(['todos'], fetchTodos)` query are unmounted and no longer in use.
- Since there are no more active instances of this query, a cache timeout is set using `cacheTime` to delete and garbage collect the query (defaults to **5 minutes**).
- Before the cache timeout has completed another instance of `useQuery('todos', fetchTodos)` mounts. The query immediately returns the available cached value while the `fetchTodos` function is being run in the background to populate the query with a fresh value.
- The final instance of `useQuery('todos', fetchTodos)` unmounts.
- No more instances of `useQuery('todos', fetchTodos)` appear within **5 minutes**.
- Before the cache timeout has completed another instance of `useQuery(['todos'], fetchTodos)` mounts. The query immediately returns the available cached value while the `fetchTodos` function is being run in the background to populate the query with a fresh value.
- The final instance of `useQuery(['todos'], fetchTodos)` unmounts.
- No more instances of `useQuery(['todos'], fetchTodos)` appear within **5 minutes**.
- This query and its data are deleted and garbage collected.
5 changes: 2 additions & 3 deletions docs/src/pages/guides/default-query-function.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ If you find yourself wishing for whatever reason that you could just share the s

```js
// Define a default query function that will receive the query key
// the queryKey is guaranteed to be an Array here
const defaultQueryFn = async ({ queryKey }) => {
const { data } = await axios.get(`https://jsonplaceholder.typicode.com${queryKey[0]}`);
return data;
Expand All @@ -32,14 +31,14 @@ function App() {

// All you have to do now is pass a key!
function Posts() {
const { status, data, error, isFetching } = useQuery('/posts')
const { status, data, error, isFetching } = useQuery(['/posts'])

// ...
}

// You can even leave out the queryFn and just go straight into options
function Post({ postId }) {
const { status, data, error, isFetching } = useQuery(`/posts/${postId}`, {
const { status, data, error, isFetching } = useQuery([`/posts/${postId}`], {
enabled: !!postId,
})

Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/guides/disabling-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function Todos() {
error,
refetch,
isFetching,
} = useQuery('todos', fetchTodoList, {
} = useQuery(['todos'], fetchTodoList, {
enabled: false,
})

Expand Down
25 changes: 12 additions & 13 deletions docs/src/pages/guides/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,30 @@ A query filter is an object with certain conditions to match a query with:
await queryClient.cancelQueries()

// Remove all inactive queries that begin with `posts` in the key
queryClient.removeQueries('posts', { inactive: true })
queryClient.removeQueries(['posts'], { type: 'inactive' })

// Refetch all active queries
await queryClient.refetchQueries({ active: true })
await queryClient.refetchQueries({ type: 'active' })

// Refetch all active queries that begin with `posts` in the key
await queryClient.refetchQueries('posts', { active: true })
await queryClient.refetchQueries(['posts'], { type: 'active' })
```

A query filter object supports the following properties:

- `exact?: boolean`
- If you don't want to search queries inclusively by query key, you can pass the `exact: true` option to return only the query with the exact query key you have passed.
- `active?: boolean`
- When set to `true` it will match active queries.
- When set to `false` it will match inactive queries.
- `inactive?: boolean`
- When set to `true` it will match inactive queries.
- When set to `false` it will match active queries.
- `type?: 'active' | 'inactive' | 'all'`
- Defaults to `all`
- When set to `active` it will match active queries.
- When set to `inactive` it will match inactive queries.
- `stale?: boolean`
- When set to `true` it will match stale queries.
- When set to `false` it will match fresh queries.
- `fetching?: boolean`
- When set to `true` it will match queries that are currently fetching.
- When set to `false` it will match queries that are not fetching.
- `fetchStatus?: FetchStatus`
- When set to `fetching` it will match queries that are currently fetching.
- When set to `paused` it will match queries that wanted to fetch, but have been `paused`.
- When set to `idle` it will match queries that are not fetching.
- `predicate?: (query: Query) => boolean`
- This predicate function will be called for every single query in the cache and be expected to return truthy for queries that are `found`.
- `queryKey?: QueryKey`
Expand All @@ -53,7 +52,7 @@ A mutation filter is an object with certain conditions to match a mutation with:
await queryClient.isMutating()

// Filter mutations by mutationKey
await queryClient.isMutating({ mutationKey: "post" })
await queryClient.isMutating({ mutationKey: ["post"] })

// Filter mutations using a predicate function
await queryClient.isMutating({ predicate: (mutation) => mutation.options.variables?.id === 1 })
Expand Down
14 changes: 7 additions & 7 deletions docs/src/pages/guides/infinite-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function Projects() {
isFetching,
isFetchingNextPage,
status,
} = useInfiniteQuery('projects', fetchProjects, {
} = useInfiniteQuery(['projects'], fetchProjects, {
getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
})

Expand Down Expand Up @@ -100,7 +100,7 @@ When an infinite query becomes `stale` and needs to be refetched, each group is
If you only want to actively refetch a subset of all pages, you can pass the `refetchPage` function to `refetch` returned from `useInfiniteQuery`.

```js
const { refetch } = useInfiniteQuery('projects', fetchProjects, {
const { refetch } = useInfiniteQuery(['projects'], fetchProjects, {
getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
})

Expand Down Expand Up @@ -132,7 +132,7 @@ function Projects() {
isFetchingNextPage,
fetchNextPage,
hasNextPage,
} = useInfiniteQuery('projects', fetchProjects, {
} = useInfiniteQuery(['projects'], fetchProjects, {
getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
})

Expand All @@ -146,7 +146,7 @@ function Projects() {
Bi-directional lists can be implemented by using the `getPreviousPageParam`, `fetchPreviousPage`, `hasPreviousPage` and `isFetchingPreviousPage` properties and functions.

```js
useInfiniteQuery('projects', fetchProjects, {
useInfiniteQuery(['projects'], fetchProjects, {
getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
getPreviousPageParam: (firstPage, pages) => firstPage.prevCursor,
})
Expand All @@ -157,7 +157,7 @@ useInfiniteQuery('projects', fetchProjects, {
Sometimes you may want to show the pages in reversed order. If this is case, you can use the `select` option:

```js
useInfiniteQuery('projects', fetchProjects, {
useInfiniteQuery(['projects'], fetchProjects, {
select: data => ({
pages: [...data.pages].reverse(),
pageParams: [...data.pageParams].reverse(),
Expand All @@ -170,7 +170,7 @@ useInfiniteQuery('projects', fetchProjects, {
Manually removing first page:

```js
queryClient.setQueryData('projects', data => ({
queryClient.setQueryData(['projects'], data => ({
pages: data.pages.slice(1),
pageParams: data.pageParams.slice(1),
}))
Expand All @@ -183,7 +183,7 @@ const newPagesArray = oldPagesArray?.pages.map((page) =>
page.filter((val) => val.id !== updatedId)
) ?? []

queryClient.setQueryData('projects', data => ({
queryClient.setQueryData(['projects'], data => ({
pages: newPagesArray,
pageParams: data.pageParams,
}))
Expand Down
18 changes: 9 additions & 9 deletions docs/src/pages/guides/initial-query-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ There may be times when you already have the initial data for a query available

```js
function Todos() {
const result = useQuery('todos', () => fetch('/todos'), {
const result = useQuery(['todos'], () => fetch('/todos'), {
initialData: initialTodos,
})
}
Expand All @@ -34,7 +34,7 @@ By default, `initialData` is treated as totally fresh, as if it were just fetche
```js
function Todos() {
// Will show initialTodos immediately, but also immediately refetch todos after mount
const result = useQuery('todos', () => fetch('/todos'), {
const result = useQuery(['todos'], () => fetch('/todos'), {
initialData: initialTodos,
})
}
Expand All @@ -45,7 +45,7 @@ By default, `initialData` is treated as totally fresh, as if it were just fetche
```js
function Todos() {
// Show initialTodos immediately, but won't refetch until another interaction event is encountered after 1000 ms
const result = useQuery('todos', () => fetch('/todos'), {
const result = useQuery(['todos'], () => fetch('/todos'), {
initialData: initialTodos,
staleTime: 1000,
})
Expand All @@ -56,7 +56,7 @@ By default, `initialData` is treated as totally fresh, as if it were just fetche
```js
function Todos() {
// Show initialTodos immediately, but won't refetch until another interaction event is encountered after 1000 ms
const result = useQuery('todos', () => fetch('/todos'), {
const result = useQuery(['todos'], () => fetch('/todos'), {
initialData: initialTodos,
staleTime: 60 * 1000 // 1 minute
// This could be 10 seconds ago or 10 minutes ago
Expand All @@ -74,7 +74,7 @@ If the process for accessing a query's initial data is intensive or just not som

```js
function Todos() {
const result = useQuery('todos', () => fetch('/todos'), {
const result = useQuery(['todos'], () => fetch('/todos'), {
initialData: () => {
return getExpensiveTodos()
},
Expand All @@ -91,7 +91,7 @@ function Todo({ todoId }) {
const result = useQuery(['todo', todoId], () => fetch('/todos'), {
initialData: () => {
// Use a todo from the 'todos' query as the initial data for this todo query
return queryClient.getQueryData('todos')?.find(d => d.id === todoId)
return queryClient.getQueryData(['todos'])?.find(d => d.id === todoId)
},
})
}
Expand All @@ -105,9 +105,9 @@ Getting initial data from the cache means the source query you're using to look
function Todo({ todoId }) {
const result = useQuery(['todo', todoId], () => fetch(`/todos/${todoId}`), {
initialData: () =>
queryClient.getQueryData('todos')?.find(d => d.id === todoId),
queryClient.getQueryData(['todos'])?.find(d => d.id === todoId),
initialDataUpdatedAt: () =>
queryClient.getQueryState('todos')?.dataUpdatedAt,
queryClient.getQueryState(['todos'])?.dataUpdatedAt,
})
}
```
Expand All @@ -121,7 +121,7 @@ function Todo({ todoId }) {
const result = useQuery(['todo', todoId], () => fetch(`/todos/${todoId}`), {
initialData: () => {
// Get the query state
const state = queryClient.getQueryState('todos')
const state = queryClient.getQueryState(['todos'])

// If the query exists and has data that is no older than 10 seconds...
if (state && Date.now() - state.dataUpdatedAt <= 10 * 1000) {
Expand Down
4 changes: 2 additions & 2 deletions docs/src/pages/guides/invalidations-from-mutations.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ const queryClient = useQueryClient()
// When this mutation succeeds, invalidate any queries with the `todos` or `reminders` query key
const mutation = useMutation(addTodo, {
onSuccess: () => {
queryClient.invalidateQueries('todos')
queryClient.invalidateQueries('reminders')
queryClient.invalidateQueries(['todos'])
queryClient.invalidateQueries(['reminders'])
},
})
```
Expand Down
Loading