react-query v4 공식문서 : Optimistic Updates

👾·2022년 8월 12일
0

react-query

목록 보기
22/27
post-thumbnail

공식문서 : https://tanstack.com/query/v4/docs/guides/optimistic-updates

Optimistic Updates

mutation을 수행하기 전에, state를 낙관적으로 업데이트하면 mutation이 실패할 가능성이 있다. 이러한 대부분의 실패 사례에서, 낙관적인 쿼리들에 대해 refetch를 트리거하여 실제 서버 state로 되돌릴 수 있다. 그러나 일부 상황에서는 refetch가 제대로 작동하지 않을 수 있으며 mutation 에러는 refetch를 불가능하게 하는 일종의 서버 이슈를 나타낼 수 있다. 이 경우, 대신 업데이트를 롤백하도록 선택할 수 있다.

이를 위해, useMutationonMutate 핸들러 옵션을 사용하면 나중에 onErroronSettled 핸들러 모두에 마지막 인수로 전달될 값을 반환할 수 있다. 대부분의 경우, 롤백 함수를 전달하는것이 가장 유용하다.

Updating a list of todos when adding a new todo

const queryClient = useQueryClient()

useMutation(updateTodo, {
  // When mutate is called:
  onMutate: async newTodo => {
    // Cancel any outgoing refetches (so they don't overwrite our optimistic update)
    await queryClient.cancelQueries(['todos'])

    // Snapshot the previous value
    const previousTodos = queryClient.getQueryData(['todos'])

    // Optimistically update to the new value
    queryClient.setQueryData(['todos'], old => [...old, newTodo])

    // Return a context object with the snapshotted value
    return { previousTodos }
  },
  // If the mutation fails, use the context returned from onMutate to roll back
  onError: (err, newTodo, context) => {
    queryClient.setQueryData(['todos'], context.previousTodos)
  },
  // Always refetch after error or success:
  onSettled: () => {
    queryClient.invalidateQueries(['todos'])
  },
})

Updating a single todo

useMutation(updateTodo, {
  // When mutate is called:
  onMutate: async newTodo => {
    // Cancel any outgoing refetches (so they don't overwrite our optimistic update)
    await queryClient.cancelQueries(['todos', newTodo.id])

    // Snapshot the previous value
    const previousTodo = queryClient.getQueryData(['todos', newTodo.id])

    // Optimistically update to the new value
    queryClient.setQueryData(['todos', newTodo.id], newTodo)

    // Return a context with the previous and new todo
    return { previousTodo, newTodo }
  },
  // If the mutation fails, use the context we returned above
  onError: (err, newTodo, context) => {
    queryClient.setQueryData(
      ['todos', context.newTodo.id],
      context.previousTodo
    )
  },
  // Always refetch after error or success:
  onSettled: newTodo => {
    queryClient.invalidateQueries(['todos', newTodo.id])
  },
})

원하는 경우 별도의 onErroronSuccess 핸들러 대신 onSettled 함수를 사용할 수도 있다.

useMutation(updateTodo, {
  // ...
  onSettled: (newTodo, error, variables, context) => {
    if (error) {
      // do something
    }
  },
})

0개의 댓글