Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,14 @@
"label": "Infinite Queries",
"to": "guides/infinite-queries"
},
{
"label": "Placeholder Query Data",
"to": "guides/placeholder-query-data"
},
{
"label": "Initial Query Data",
"to": "guides/initial-query-data"
},
{
"label": "Placeholder Query Data",
"to": "guides/placeholder-query-data"
},
{
"label": "Prefetching",
"to": "guides/prefetching"
Expand Down
5 changes: 4 additions & 1 deletion docs/guides/dependent-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ Dependent (or serial) queries depend on previous ones to finish before they can

```tsx
// Get the user
const { data: user } = useQuery({ queryKey: ['user', email], queryFn: getUserByEmail })
const { data: user } = useQuery({
queryKey: ['user', email],
queryFn: getUserByEmail,
})

const userId = user?.id

Expand Down
8 changes: 3 additions & 5 deletions docs/guides/disabling-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ If you ever want to disable a query from automatically running, you can use the

When `enabled` is `false`:

- If the query has cached data
- The query will be initialized in the `status === 'success'` or `isSuccess` state.
- If the query does not have cached data
- The query will start in the `status === 'loading'` and `fetchStatus === 'idle'`
- If the query has cached data, then the query will be initialized in the `status === 'success'` or `isSuccess` state.
- If the query does not have cached data, then the query will start in the `status === 'loading'` and `fetchStatus === 'idle'` state.
- The query will not automatically fetch on mount.
- The query will not automatically refetch in the background
- The query will not automatically refetch in the background.
- The query will ignore query client `invalidateQueries` and `refetchQueries` calls that would normally result in the query refetching.
- `refetch` returned from `useQuery` can be used to manually trigger the query to fetch.

Expand Down
4 changes: 3 additions & 1 deletion docs/guides/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ await queryClient.isMutating()
await queryClient.isMutating({ mutationKey: ["post"] })

// Filter mutations using a predicate function
await queryClient.isMutating({ predicate: (mutation) => mutation.options.variables?.id === 1 })
await queryClient.isMutating({
predicate: (mutation) => mutation.options.variables?.id === 1,
})
```

A mutation filter object supports the following properties:
Expand Down
4 changes: 1 addition & 3 deletions docs/guides/initial-query-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,7 @@ function Todos() {
const result = useQuery({
queryKey: ['todos'],
queryFn: () => fetch('/todos'),
initialData: () => {
return getExpensiveTodos()
},
initialData: () => getExpensiveTodos(),
})
}
```
Expand Down
9 changes: 6 additions & 3 deletions docs/guides/optimistic-updates.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ useMutation({
mutationFn: updateTodo,
// When mutate is called:
onMutate: async newTodo => {
// Cancel any outgoing refetches (so they don't overwrite our optimistic update)
// Cancel any outgoing refetches
// (so they don't overwrite our optimistic update)
await queryClient.cancelQueries({ queryKey: ['todos'] })

// Snapshot the previous value
Expand All @@ -28,7 +29,8 @@ useMutation({
// Return a context object with the snapshotted value
return { previousTodos }
},
// If the mutation fails, use the context returned from onMutate to roll back
// If the mutation fails,
// use the context returned from onMutate to roll back
onError: (err, newTodo, context) => {
queryClient.setQueryData(['todos'], context.previousTodos)
},
Expand All @@ -46,7 +48,8 @@ useMutation({
mutationFn: updateTodo,
// When mutate is called:
onMutate: async newTodo => {
// Cancel any outgoing refetches (so they don't overwrite our optimistic update)
// Cancel any outgoing refetches
// (so they don't overwrite our optimistic update)
await queryClient.cancelQueries({ queryKey: ['todos', newTodo.id] })

// Snapshot the previous value
Expand Down
5 changes: 4 additions & 1 deletion docs/guides/paginated-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ title: Paginated / Lagged Queries
Rendering paginated data is a very common UI pattern and in React Query, it "just works" by including the page information in the query key:

```tsx
const result = useQuery({ queryKey: ['projects', page], queryFn: fetchProjects })
const result = useQuery({
queryKey: ['projects', page],
queryFn: fetchProjects
})
```

However, if you run this simple example, you might notice something strange:
Expand Down
9 changes: 7 additions & 2 deletions docs/guides/placeholder-query-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ If the process for accessing a query's placeholder data is intensive or just not
```tsx
function Todos() {
const placeholderData = useMemo(() => generateFakeTodos(), [])
const result = useQuery({ queyKey: ['todos'], queryFn: () => fetch('/todos'), placeholderData })
const result = useQuery({
queyKey: ['todos'],
queryFn: () => fetch('/todos'),
placeholderData
})
}
```

Expand All @@ -49,7 +53,8 @@ function Todo({ blogPostId }) {
queryKey: ['blogPost', blogPostId],
queryFn: () => fetch(`/blogPosts/${blogPostId}`),
placeholderData: () => {
// Use the smaller/preview version of the blogPost from the 'blogPosts' query as the placeholder data for this blogPost query
// Use the smaller/preview version of the blogPost from the 'blogPosts'
// query as the placeholder data for this blogPost query
return queryClient
.getQueryData(['blogPosts'])
?.find(d => d.id === blogPostId)
Expand Down
10 changes: 8 additions & 2 deletions docs/guides/queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ For **most** queries, it's usually sufficient to check for the `isLoading` state

```tsx
function Todos() {
const { isLoading, isError, data, error } = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
const { isLoading, isError, data, error } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})

if (isLoading) {
return <span>Loading...</span>
Expand All @@ -70,7 +73,10 @@ If booleans aren't your thing, you can always use the `status` state as well:

```tsx
function Todos() {
const { status, data, error } = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
const { status, data, error } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})

if (status === 'loading') {
return <span>Loading...</span>
Expand Down
32 changes: 21 additions & 11 deletions docs/guides/query-cancellation.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,12 @@ An `AbortSignal` can be set in the client `request` method.
```tsx
const client = new GraphQLClient(endpoint)

const query = useQuery({ queryKey: ['todos'], queryFn: ({ signal }) => {
client.request({ document: query, signal })
}})
const query = useQuery({
queryKey: ['todos'],
queryFn: ({ signal }) => {
client.request({ document: query, signal })
}
})
```

## Using `graphql-request` version less than v4.0.0
Expand All @@ -137,17 +140,24 @@ const query = useQuery({
You might want to cancel a query manually. For example, if the request takes a long time to finish, you can allow the user to click a cancel button to stop the request. To do this, you just need to call `queryClient.cancelQueries({ queryKey })`, which will cancel the query and revert it back to its previous state. If `promise.cancel` is available, or you have consumed the `signal` passed to the query function, React Query will additionally also cancel the Promise.

```tsx
const query = useQuery({ queryKey: ['todos'], queryFn: async ({ signal }) => {
const resp = await fetch('/todos', { signal })
return resp.json()
}})
const query = useQuery({
queryKey: ['todos'],
queryFn: async ({ signal }) => {
const resp = await fetch('/todos', { signal })
return resp.json()
}
})

const queryClient = useQueryClient()

return (
<button onClick={(e) => {
e.preventDefault()
queryClient.cancelQueries({ queryKey: ['todos'] })
}}>Cancel</button>
<button
onClick={(e) => {
e.preventDefault()
queryClient.cancelQueries({ queryKey: ['todos'] })
}}
>
Cancel
</button>
)
```
10 changes: 8 additions & 2 deletions docs/guides/query-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ useQuery({ queryKey: ['todos', todoId], queryFn: async () => {
const data = await fetchTodoById(todoId)
return data
}})
useQuery({ queryKey: ['todos', todoId], queryFn: ({ queryKey }) => fetchTodoById(queryKey[1])})
useQuery({
queryKey: ['todos', todoId],
queryFn: ({ queryKey }) => fetchTodoById(queryKey[1]),
})
```

## Handling and Throwing Errors
Expand Down Expand Up @@ -60,7 +63,10 @@ Query keys are not just for uniquely identifying the data you are fetching, but

```tsx
function Todos({ status, page }) {
const result = useQuery({ queryKey: ['todos', { status, page }], queryFn: fetchTodoList })
const result = useQuery({
queryKey: ['todos', { status, page }],
queryFn: fetchTodoList,
})
}

// Access the key, status and page variables in your query function!
Expand Down
54 changes: 43 additions & 11 deletions docs/guides/query-invalidation.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,55 @@ const queryClient = useQueryClient()
queryClient.invalidateQueries({ queryKey: ['todos'] })

// Both queries below will be invalidated
const todoListQuery = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
const todoListQuery = useQuery({ queryKey: ['todos', { page: 1 }], queryFn: fetchTodoList })
const todoListQuery = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
const todoListQuery = useQuery({
queryKey: ['todos', { page: 1 }],
queryFn: fetchTodoList,
})
```

You can even invalidate queries with specific variables by passing a more specific query key to the `invalidateQueries` method:

```tsx
queryClient.invalidateQueries({ queryKey: ['todos', { type: 'done' }]})
queryClient.invalidateQueries({
queryKey: ['todos', { type: 'done' },
})

// The query below will be invalidated
const todoListQuery = useQuery({ queryKey: ['todos', { type: 'done' }], queryFn: fetchTodoList })
const todoListQuery = useQuery({
queryKey: ['todos', { type: 'done' }],
queryFn: fetchTodoList,
})

// However, the following query below will NOT be invalidated
const todoListQuery = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
const todoListQuery = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
```

The `invalidateQueries` API is very flexible, so even if you want to **only** invalidate `todos` queries that don't have any more variables or subkeys, you can pass an `exact: true` option to the `invalidateQueries` method:

```tsx
queryClient.invalidateQueries({ queryKey: ['todos'], exact: true })
queryClient.invalidateQueries({
queryKey: ['todos'],
exact: true,
})

// The query below will be invalidated
const todoListQuery = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
const todoListQuery = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})

// However, the following query below will NOT be invalidated
const todoListQuery = useQuery({ queryKey: ['todos', { type: 'done' }], queryFn: fetchTodoList })
const todoListQuery = useQuery({
queryKey: ['todos', { type: 'done' }],
queryFn: fetchTodoList,
})
```

If you find yourself wanting **even more** granularity, you can pass a predicate function to the `invalidateQueries` method. This function will receive each `Query` instance from the query cache and allow you to return `true` or `false` for whether you want to invalidate that query:
Expand All @@ -71,11 +94,20 @@ queryClient.invalidateQueries({
})

// The query below will be invalidated
const todoListQuery = useQuery({ queryKey: ['todos', { version: 20 }], queryFn: fetchTodoList })
const todoListQuery = useQuery({
queryKey: ['todos', { version: 20 }],
queryFn: fetchTodoList,
}),

// The query below will be invalidated
const todoListQuery = useQuery({ queryKey: ['todos', { version: 10 }], queryFn: fetchTodoList })
const todoListQuery = useQuery({
queryKey: ['todos', { version: 10 }],
queryFn: fetchTodoList,
}),

// However, the following query below will NOT be invalidated
const todoListQuery = useQuery({ queryKey: ['todos', { version: 5 }], queryFn: fetchTodoList })
const todoListQuery = useQuery({
queryKey: ['todos', { version: 5 }],
queryFn: fetchTodoList,
}),
```
5 changes: 4 additions & 1 deletion docs/guides/query-keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ Since query keys uniquely describe the data they are fetching, they should inclu

```tsx
function Todos({ todoId }) {
const result = useQuery({ queryKey: ['todos', todoId], queryFn: () => fetchTodoById(todoId) })
const result = useQuery({
queryKey: ['todos', todoId],
queryFn: () => fetchTodoById(todoId),
})
}
```

Expand Down
6 changes: 5 additions & 1 deletion docs/guides/ssr.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ export async function getStaticProps() {
}

function Posts(props) {
const { data } = useQuery({ queryKey: ['posts'], queryFn: getPosts, initialData: props.posts })
const { data } = useQuery({
queryKey: ['posts'],
queryFn: getPosts,
initialData: props.posts,
})

// ...
}
Expand Down
10 changes: 8 additions & 2 deletions docs/guides/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ Given the following custom hook:

```ts
function useFetchData() {
return useQuery({ queryKey: ['fetchData'], queryFn: () => request('/api/data') });
return useQuery({
queryKey: ['fetchData'],
queryFn: () => request('/api/data'),
});
}
```

Expand Down Expand Up @@ -178,7 +181,10 @@ const expectation = nock('http://example.com')
Now we can safely run our tests, the trick here is to await for the data assertion to pass:

```ts
const { result, waitFor } = renderHook(() => useInfiniteQueryCustomHook(), { wrapper });
const { result, waitFor } = renderHook(
() => useInfiniteQueryCustomHook(),
{ wrapper },
);

await waitFor(() => result.current.isSuccess);

Expand Down
5 changes: 4 additions & 1 deletion docs/guides/updates-from-mutation-responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ mutation.mutate({

// The query below will be updated with the response from the
// successful mutation
const { status, data, error } = useQuery({ queryKey: ['todo', { id: 5 }], queryFn: fetchTodoById })
const { status, data, error } = useQuery({
queryKey: ['todo', { id: 5 }],
queryFn: fetchTodoById,
})
```

You might want to tie the `onSuccess` logic into a reusable mutation, for that you can
Expand Down
6 changes: 5 additions & 1 deletion docs/guides/window-focus-refetching.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ function App() {
#### Disabling Per-Query

```tsx
useQuery({ queryKey: ['todos'], queryFn: fetchTodos, refetchOnWindowFocus: false })
useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
refetchOnWindowFocus: false,
})
```

## Custom Window Focus Event
Expand Down
Loading