Skip to content

Commit

Permalink
Merge branch 'main' into feature/typed-query-key
Browse files Browse the repository at this point in the history
  • Loading branch information
TkDodo committed Oct 20, 2023
2 parents efe191d + 9566984 commit 41cb821
Show file tree
Hide file tree
Showing 133 changed files with 6,989 additions and 6,287 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pr.yml
Expand Up @@ -35,7 +35,7 @@ jobs:
- name: Get appropriate base and head commits for `nx affected` commands
uses: nrwl/nx-set-shas@v3
with:
main-branch-name: 'rc'
main-branch-name: 'main'
- run: |
echo "BASE: ${{ env.NX_BASE }}"
echo "HEAD: ${{ env.NX_HEAD }}"
Expand Down
14 changes: 6 additions & 8 deletions README.md
@@ -1,6 +1,6 @@
<img src="https://static.scarf.sh/a.png?x-pxid=be2d8a11-9712-4c1d-9963-580b2d4fb133" />

![TanStack Query Header](https://github.com/TanStack/query/raw/rc/media/repo-header.png)
![TanStack Query Header](https://github.com/TanStack/query/raw/main/media/repo-header.png)

Hooks for fetching, caching and updating asynchronous data in React, Solid, Svelte and Vue

Expand All @@ -12,8 +12,8 @@ Hooks for fetching, caching and updating asynchronous data in React, Solid, Svel
<img src="https://github.com/TanStack/query/workflows/react-query%20tests/badge.svg" />
</a><a href="https://www.npmjs.com/package/@tanstack/query-core" target="\_parent">
<img alt="" src="https://img.shields.io/npm/dm/@tanstack/query-core.svg" />
</a><a href="https://bundlejs.com/?q=%40tanstack%2Freact-query%40rc&config=%7B%22esbuild%22%3A%7B%22external%22%3A%5B%22react%22%2C%22react-dom%22%5D%7D%7D&badge=" target="\_parent">
<img alt="" src="https://deno.bundlejs.com/?q=@tanstack/react-query@rc&config={%22esbuild%22:{%22external%22:[%22react%22,%22react-dom%22]}}&badge=detailed" />
</a><a href="https://bundlejs.com/?q=%40tanstack%2Freact-query&config=%7B%22esbuild%22%3A%7B%22external%22%3A%5B%22react%22%2C%22react-dom%22%5D%7D%7D&badge=" target="\_parent">
<img alt="" src="https://deno.bundlejs.com/?q=@tanstack/react-query&config={%22esbuild%22:{%22external%22:[%22react%22,%22react-dom%22]}}&badge=detailed" />
</a><a href="#badge">
<img alt="semantic-release" src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg">
</a><a href="https://github.com/TanStack/query/discussions">
Expand All @@ -30,8 +30,9 @@ Enjoy this library? Try the entire [TanStack](https://tanstack.com)! [TanStack T

## Visit [tanstack.com/query](https://tanstack.com/query) for docs, guides, API and more!

Still on **React Query v2**? No problem! Check out the v2 docs here: https://github.com/TanStack/query/tree/2.x/docs/src/pages/docs. <br />
Still on **React Query v3**? No problem! Check out the v3 docs here: https://tanstack.com/query/v3/docs/.
Still on **React Query v2**? No problem! Check out the v2 docs here: https://github.com/TanStack/query/tree/2.x/docs/src/pages/docs.<br />
Still on **React Query v3**? No problem! Check out the v3 docs here: https://tanstack.com/query/v3/docs/.<br />
Still on **React Query v4**? No problem! Check out the v4 docs here: https://tanstack.com/query/v4/docs/.

## Quick Features

Expand All @@ -45,9 +46,6 @@ Still on **React Query v3**? No problem! Check out the v3 docs here: https://tan
- Request Cancellation
- [React Suspense](https://react.dev/reference/react/Suspense) + Fetch-As-You-Render Query Prefetching
- Dedicated Devtools
- <a href="https://bundlephobia.com/package/@tanstack/react-query@latest" target="\_parent">
<img alt="" src="https://badgen.net/bundlephobia/minzip/@tanstack/react-query" />
</a> (depending on features imported)

### [Become a Sponsor!](https://github.com/sponsors/tannerlinsley/)

Expand Down
37 changes: 35 additions & 2 deletions docs/config.json
Expand Up @@ -243,8 +243,12 @@
"to": "react/examples/react/auto-refetching"
},
{
"label": "Optimistic Updates in TypeScript",
"to": "react/examples/react/optimistic-updates-typescript"
"label": "Optimistic Updates (UI)",
"to": "react/examples/react/optimistic-updates-ui"
},
{
"label": "Optimistic Updates (Cache)",
"to": "react/examples/react/optimistic-updates-cache"
},
{
"label": "Pagination",
Expand Down Expand Up @@ -446,6 +450,35 @@
{
"label": "Overview",
"to": "solid/overview"
},
{
"label": "Devtools",
"to": "solid/devtools"
}
]
},
{
"label": "Examples",
"children": [
{
"label": "Simple",
"to": "solid/examples/solid/simple"
},
{
"label": "Basic",
"to": "solid/examples/solid/basic-typescript"
},
{
"label": "Basic w/ GraphQL-Request",
"to": "solid/examples/solid/basic-graphql-request"
},
{
"label": "Default Query Function",
"to": "solid/examples/solid/default-query-function"
},
{
"label": "Solid Start",
"to": "solid/examples/solid/solid-start-streaming"
}
]
}
Expand Down
41 changes: 33 additions & 8 deletions docs/react/community/liaoliao666-react-query-kit.md
Expand Up @@ -11,7 +11,7 @@ title: React Query Kit
- Manage `queryKey` in a type-safe way
- Generate a custom ReactQuery hook quickly
- Make `queryClient`'s operations clearly associated with custom ReactQuery hooks
- Set defaultOptions for custom ReactQuery hooks easier and clearer
- Middleware

## Installation

Expand Down Expand Up @@ -41,16 +41,15 @@ const usePost = createQuery<Response, Variables, Error>({
primaryKey: '/posts',
queryFn: ({ queryKey: [primaryKey, variables] }) => {
// primaryKey equals to '/posts'
return fetch(`${primaryKey}/${variables.id}`).then(res => res.json())
return fetch(`${primaryKey}/${variables.id}`).then((res) => res.json())
},
suspense: true
})

const variables = { id: 1 }

export default function Page() {
// queryKey equals to ['/posts', { id: 1 }]
const { data } = usePost({ variables, suspense: true })
const { data } = usePost({ variables })

return (
<div>
Expand All @@ -62,14 +61,12 @@ export default function Page() {

console.log(usePost.getKey()) // ['/posts']
console.log(usePost.getKey(variables)) // ['/posts', { id: 1 }]
console.log(queryClient.getQueryData(usePost.getKey(variables))) // Response | undefined

export async function getStaticProps() {
const queryClient = new QueryClient()

await queryClient.prefetchQuery({
queryKey: usePost.getKey(variables),
queryFn: usePost.queryFn
})
await queryClient.prefetchQuery(usePost.getFetchOptions(variables))

return {
props: {
Expand All @@ -79,4 +76,32 @@ export async function getStaticProps() {
}
```

## Middleware

You can also execute logic before and after hooks via middleware. [See details](https://github.com/liaoliao666/react-query-kit#middleware)

```ts
import { createQuery, Middleware } from 'react-query-kit'

const disabledIfHasData: Middleware<QueryHook<Response, Variables>> = (
useQueryNext,
) => {
return (options) => {
const client = useQueryClient()
const hasData = () =>
!!client.getQueryData(useUser.getKey(options.variables))

return useQueryNext({
...options,
enabled: options.enabled ?? !hasData(),
})
}
}

createQuery<Response, Variables>({
// ...
use: [disabledIfHasData],
})
```

Check the complete documentation on [GitHub](https://github.com/liaoliao666/react-query-kit).
8 changes: 4 additions & 4 deletions docs/react/devtools.md
Expand Up @@ -16,11 +16,11 @@ When you begin your React Query journey, you'll want these devtools by your side
The devtools are a separate package that you need to install:

```bash
$ npm i @tanstack/react-query-devtools@rc
$ npm i @tanstack/react-query-devtools
# or
$ pnpm add @tanstack/react-query-devtools@rc
$ pnpm add @tanstack/react-query-devtools
# or
$ yarn add @tanstack/react-query-devtools@rc
$ yarn add @tanstack/react-query-devtools
```

You can import the devtools like this:
Expand Down Expand Up @@ -78,7 +78,7 @@ import { Example } from './Example'
const queryClient = new QueryClient()

const ReactQueryDevtoolsProduction = React.lazy(() =>
import('@tanstack/react-query-devtools/build/lib/index.prod.js').then(
import('@tanstack/react-query-devtools/build/modern/production.js').then(
(d) => ({
default: d.ReactQueryDevtools,
}),
Expand Down
11 changes: 11 additions & 0 deletions docs/react/guides/migrating-to-v5.md
Expand Up @@ -136,6 +136,17 @@ A few notes about how codemod works:

`onSuccess`, `onError` and `onSettled` have been removed from Queries. They haven't been touched for Mutations. Please see [this RFC](https://github.com/TanStack/query/discussions/5279) for motivations behind this change and what to do instead.

### The `refetchInteval` callback function only gets `query` passed

This streamlines how callbacks are invoked (the `refetchOnWindowFocus`, `refetchOnMount` and `refetchOnReconnect` callbacks all only get the query passed as well), and it fixes some typing issues when callbacks get data transformed by `select`.

```diff
- refetchInterval: number | false | ((data: TData | undefined, query: Query) => number | false | undefined)
+ refetchInterval: number | false | ((query: Query) => number | false | undefined)
```

You can still access data with `query.state.data`, however, it will not be data that has been transformed by `select`. If you need to access the transformed data, you can call the transformation again on `query.state.data`.

### The `remove` method has been removed from useQuery

Previously, remove method used to remove the query from the queryCache without informing observers about it. It was best used to remove data imperatively that is no longer needed, e.g. when logging a user out.
Expand Down
12 changes: 4 additions & 8 deletions docs/react/guides/optimistic-updates.md
Expand Up @@ -31,26 +31,22 @@ you will then have access to `addTodoMutation.variables`, which contain the adde
<li key={todo.id}>{todo.text}</li>
))}
{isPending && (
<li
key={String(submittedAt)}
style={{ opacity: 0.5 }}
>
<li style={{ opacity: 0.5 }}>
{variables}
</li>
)}
</ul>
```
[//]: # 'ExampleUI2'

The `submittedAt` property is a timestamp that is set when `mutate` is invoked. This is useful to create a unique key for the pending todo item. We've also added an `opacity` to indicate that this item is only temporarily here. Once the mutation completes, the item will be removed because the mutation is no longer `pending`. Given that the refetch succeeded, we should see the item as a "normal item" in our list.
We're rendering a temporary item with a different `opacity` as long as the mutation is pending. Once it completes, the item will automatically no longer be rendered. Given that the refetch succeeded, we should see the item as a "normal item" in our list.

If the mutation errors, the item will also disappear. But we could continue to show it, if we want, by checking for the `isError` state of the mutation. `variables` are _not_ cleared when the mutation errors, so we can still access them, maybe even show a retry button:

[//]: # 'ExampleUI3'
```tsx
{isError && (
<li
key={String(submittedAt)}
style={{ color: 'red' }}
>
{variables}
Expand Down Expand Up @@ -83,11 +79,11 @@ const variables = useMutationState<string>({
```
[//]: # 'ExampleUI4'

`variables` will be an `Array`, because there might be multiple mutations running at the same time. This will even make displaying concurrent optimistic updates a breeze.
`variables` will be an `Array`, because there might be multiple mutations running at the same time. If we need a unique key for the items, we can also select `mutation.state.submittedAt`. This will even make displaying concurrent optimistic updates a breeze.

## Via the cache

When you optimistically update your state before performing a mutation, there is a chance that the mutation will fail. In most of these failure cases, you can just trigger a refetch for your optimistic queries to revert them to their true server state. In some circumstances though, refetching may not work correctly and the mutation error could represent some type of server issue that won't make it possible to refetch. In this event, you can instead choose to rollback your update.
When you optimistically update your state before performing a mutation, there is a chance that the mutation will fail. In most of these failure cases, you can just trigger a refetch for your optimistic queries to revert them to their true server state. In some circumstances though, refetching may not work correctly and the mutation error could represent some type of server issue that won't make it possible to refetch. In this event, you can instead choose to roll back your update.

To do this, `useMutation`'s `onMutate` handler option allows you to return a value that will later be passed to both `onError` and `onSettled` handlers as the last argument. In most cases, it is most useful to pass a rollback function.

Expand Down
2 changes: 1 addition & 1 deletion docs/react/guides/query-functions.md
Expand Up @@ -104,7 +104,7 @@ The `QueryFunctionContext` is the object passed to each query function. It consi
- [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) instance provided by TanStack Query
- Can be used for [Query Cancellation](../guides/query-cancellation)
- `meta: Record<string, unknown> | undefined`
- an optional field you can fill with additional information about your query#
- an optional field you can fill with additional information about your query

Additionally, [Infinite Queries](../guides/infinite-queries) get the following options passed:

Expand Down
8 changes: 2 additions & 6 deletions docs/react/guides/suspense.md
Expand Up @@ -111,7 +111,7 @@ Out of the box, React Query in `suspense` mode works really well as a **Fetch-on

## Suspense on the Server with streaming

If you are using `NextJs`, you can use our **experimental** integration for Suspense on the Server: `@tanstack/react-query-next-experimental`. This package will allow you to fetch data on the server (in a client component) by just calling `useQuery` (with `suspense: true`) or `useSuspenseQuery` in your component. Results will then be streamed from the server to the client as SuspenseBoundaries resolve.
If you are using `NextJs`, you can use our **experimental** integration for Suspense on the Server: `@tanstack/react-query-next-experimental`. This package will allow you to fetch data on the server (in a client component) by just calling `useSuspenseQuery` in your component. Results will then be streamed from the server to the client as SuspenseBoundaries resolve.

To achieve this, wrap your app in the `ReactQueryStreamedHydration` component:

Expand All @@ -136,8 +136,4 @@ export function Providers(props: { children: React.ReactNode }) {
}
```

For more information, check out the [NextJs Suspense Streaming Example](../examples/react/nextjs-suspense-streaming).

## Further reading

For tips on using suspense option, check the [Suspensive React Query Package](../community/suspensive-react-query) from the Community Resources.
For more information, check out the [NextJs Suspense Streaming Example](../examples/react/nextjs-suspense-streaming) and the [Advanced Rendering & Hydration](../guides/advanced-ssr) guide.
4 changes: 2 additions & 2 deletions docs/react/guides/testing.md
Expand Up @@ -82,9 +82,9 @@ const wrapper = ({ children }) => (

This will set the defaults for all queries in the component tree to "no retries". It is important to know that this will only work if your actual useQuery has no explicit retries set. If you have a query that wants 5 retries, this will still take precedence, because defaults are only taken as a fallback.

## Set cacheTime to Infinity with Jest
## Set gcTime to Infinity with Jest

If you use Jest, you can set the `cacheTime` to `Infinity` to prevent "Jest did not exit one second after the test run completed" error message. This is the default behavior on the server, and is only necessary to set if you are explicitly setting a `cacheTime`.
If you use Jest, you can set the `gcTime` to `Infinity` to prevent "Jest did not exit one second after the test run completed" error message. This is the default behavior on the server, and is only necessary to set if you are explicitly setting a `gcTime`.

## Testing Network Calls

Expand Down
2 changes: 1 addition & 1 deletion docs/react/guides/updates-from-mutation-responses.md
Expand Up @@ -51,7 +51,7 @@ const useMutateTodo = () => {

## Immutability

Updates via `setQueryData` must be performed in an _immutable_ way. **DO NOT** attempt to write directly to the cache by mutating data (that you retrieved via from the cache) in place. It might work at first but can lead to subtle bugs along the way.
Updates via `setQueryData` must be performed in an _immutable_ way. **DO NOT** attempt to write directly to the cache by mutating data (that you retrieved from the cache) in place. It might work at first but can lead to subtle bugs along the way.

[//]: # 'Example3'
```tsx
Expand Down
14 changes: 7 additions & 7 deletions docs/react/installation.md
Expand Up @@ -12,11 +12,11 @@ or a good ol' `<script>` via
### NPM

```bash
$ npm i @tanstack/react-query@rc
$ npm i @tanstack/react-query
# or
$ pnpm add @tanstack/react-query@rc
$ pnpm add @tanstack/react-query
# or
$ yarn add @tanstack/react-query@rc
$ yarn add @tanstack/react-query
```

React Query is compatible with React v18+ and works with ReactDOM and React Native.
Expand All @@ -31,7 +31,7 @@ If you're not using a module bundler or package manager, you can also use this l
<script type="module">
import React from 'https://esm.sh/react@18.2.0'
import ReactDOM from 'https://esm.sh/react-dom@18.2.0'
import { QueryClient } from 'https://esm.sh/@tanstack/react-query@rc'
import { QueryClient } from 'https://esm.sh/@tanstack/react-query'
</script>
```

Expand All @@ -57,9 +57,9 @@ opera >= 77
It is recommended to also use our [ESLint Plugin Query](./eslint/eslint-plugin-query) to help you catch bugs and inconsistencies while you code. You can install it via:

```bash
$ npm i -D @tanstack/eslint-plugin-query@rc
$ npm i -D @tanstack/eslint-plugin-query
# or
$ pnpm add -D @tanstack/eslint-plugin-query@rc
$ pnpm add -D @tanstack/eslint-plugin-query
# or
$ yarn add -D @tanstack/eslint-plugin-query@rc
$ yarn add -D @tanstack/eslint-plugin-query
```
24 changes: 21 additions & 3 deletions docs/react/reference/useMutationState.md
Expand Up @@ -5,17 +5,35 @@ title: useMutationState

`useMutationState` is a hook that gives you access to all mutations in the `MutationCache`. You can pass `filters` to it to narrow down your mutations, and `select` to transform the mutation state.

**Example 1: Get all variables of all running mutations**

```tsx
import { useMutationState } from '@tanstack/react-query'
// Get all variables of all running mutations

const variables = useMutationState({
filters: { status: 'pending' },
select: (mutation) => mutation.state.variables,
})
```

**Example 2: Get all data for specific mutations via the `mutationKey`**

```tsx
import { useMutation, useMutationState } from '@tanstack/react-query'

const mutationKey = ['posts']

// Some mutation that we want to get the state for
const mutation = useMutation({
mutationKey,
mutationFn: (newPost) => {
return axios.post('/posts', newPost)
},
})

// Get all data of all "post" mutations
const data = useMutationState({
filters: { mutationKey: ['posts'] },
// this mutation key needs to match the mutation key of the given mutation (see above)
filters: { mutationKey },
select: (mutation) => mutation.state.data,
})
```
Expand Down

0 comments on commit 41cb821

Please sign in to comment.