keepPreviousData: true,
function Todos() {
const result = useQuery('todos', () => fetch('/todos'), {
placeholderData: placeholderTodos,
})
}
function Todo({ blogPostId }) {
const result = useQuery(['blogPost', blogPostId], () => fetch(`/blogPosts/${blogPostId}`), {
placeholderData: () => {
// 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)
},
})
}
function Todos() {
// Show initialTodos immediately, but won't refetch until another interaction event is encountered after 1000 ms
const result = useQuery('todos', () => fetch('/todos'), {
initialData: initialTodos,
staleTime: 60 * 1000 // 1 minute
// This could be 10 seconds ago or 10 minutes ago
initialDataUpdatedAt: initialTodosUpdatedTimestamp // eg. 1608412420052
})
}
차이점
observer level vs cache level
const prefetchTodos = async () => {
// The results of this query will be cached like a normal query
await queryClient.prefetchQuery('todos', fetchTodos)
}
useQuery로 호출하지 않아도 미리 준비한다.
prefetch해놓고도 쓰이지 않는다면 가비지컬렉터에 의해 알아서 삭제된다.
useQuery와는 상태에 대해서는 거의 비슷함, 사이드 이펙트 부분이 좀 다르다.
리액트 16버전에서는 이벤트를 직접 받아서 동작 불가능
const CreateTodo = () => {
const mutation = useMutation(formData => {
return fetch('/api', formData)
})
const onSubmit = event => {
event.preventDefault()
mutation.mutate(new FormData(event.target))
}
return <form onSubmit={onSubmit}>...</form>
}
{mutation.error && (
<h5 onClick={() => mutation.reset()}>{mutation.error}</h5>
)}
// Invalidate every query in the cache
queryClient.invalidateQueries()
// Invalidate every query with a key that starts with `todos`
queryClient.invalidateQueries('todos')
queryClient.invalidateQueries({
predicate: query =>
query.queryKey[0] === 'todos' && query.queryKey[1]?.version >= 10,
})
// The query below will be invalidated
const todoListQuery = useQuery(['todos', { version: 20 }], fetchTodoList)
// The query below will be invalidated
const todoListQuery = useQuery(['todos', { version: 10 }], fetchTodoList)
// However, the following query below will NOT be invalidated
const todoListQuery = useQuery(['todos', { version: 5 }], fetchTodoList)
import axios from 'axios'
const query = useQuery('todos', ({ signal }) => {
// Create a new CancelToken source for this request
const CancelToken = axios.CancelToken
const source = CancelToken.source()
const promise = axios.get('/todos', {
// Pass the source token to your request
cancelToken: source.token,
})
// Cancel the request if React Query signals to abort
signal?.addEventListener('abort', () => {
source.cancel('Query was cancelled by React Query')
})
return promise
})
import axios from 'axios'
const query = useQuery('todos', ({ signal }) =>
axios.get('/todos', {
// Pass the signal to `axios`
signal,
})
)
const [queryKey] = useState('todos')
const query = useQuery(queryKey, async ({ signal }) => {
const resp = await fetch('/todos', { signal })
return resp.json()
})
const queryClient = useQueryClient()
return (
<button onClick={(e) => {
e.preventDefault()
queryClient.cancelQueries(queryKey)
}}>Cancel</button>
)
// Cancel all queries
await queryClient.cancelQueries()
// Remove all inactive queries that begin with `posts` in the key
queryClient.removeQueries('posts', { inactive: true })
// Refetch all active queries
await queryClient.refetchQueries({ active: true })
// Refetch all active queries that begin with `posts` in the key
await queryClient.refetchQueries('posts', { active: true })
// Get the number of all fetching mutations
await queryClient.isMutating()
// Filter mutations by mutationKey
await queryClient.isMutating({ mutationKey: "post" })
// Filter mutations using a predicate function
await queryClient.isMutating({ predicate: (mutation) => mutation.options.variables?.id === 1 })