skip to Main Content

Currently, my code looks like this. When mutation is successful, I have to refetch all the data because tasks will not be updated. How can I update the client-side tasks when I submit or delete a task?

  const { data: sessionData } = useSession()

  const {
    data: tasks,
    refetch: refetchTasks,
  } = api.task.getAll.useQuery(undefined, {
    enabled: sessionData?.user !== undefined,
  })

  const createTask = api.task.create.useMutation({
    onSuccess: async () => await refetchTasks(),
  })

  const createTaskValues = (values: { title: string }) =>
    createTask.mutate({ title: values.title })

  const deleteTask = api.task.delete.useMutation({
    onSuccess: async () => await refetchTasks(),
  })

PS

Using useContext() is better than calling refetch function unless you want to refetch data every time.

const utils = api.useContext()

  const createTask = api.task.create.useMutation({
    onSuccess: () => utils.task.getAll.invalidate()
  })

  const createTaskValues = (values: { title: string }) =>
    createTask.mutate({ title: values.title })

  const deleteTask = api.task.delete.useMutation({
    onSuccess: () => utils.task.getAll.invalidate()
  })

2

Answers


  1. Chosen as BEST ANSWER

    I figured out the solution by myself. I use tRPC and it provides its own callback function setData() to mutate cache. tRPC is a wrapper of React-Query though.

    This way, when mutation on the database was successful, I can mutate the cache as well.

    Now I have to use global state manager like Zustand less!

      const { data: sessionData } = useSession()
    
      const { data: tasks } = api.task.getAll.useQuery(undefined, {
        enabled: sessionData?.user !== undefined,
      })
    
      const utils = api.useContext()
    
      const createTask = api.task.create.useMutation({
        onSuccess: newTask => {
          utils.task.getAll.setData(undefined, prevTasks => {
            if (prevTasks === undefined) return [newTask]
            console.log([...prevTasks, newTask])
            return [...prevTasks, newTask]
          })
        },
      })
    
      const createTaskValues = (values: { title: string }) =>
        createTask.mutate({ title: values.title })
    
      const deleteTask = api.task.delete.useMutation({
        onSuccess: deletedTask => {
          utils.task.getAll.setData(undefined, prevTasks => {
            const tasksWithoutDeletedTask = prevTasks?.filter(
              task => task.id !== deletedTask.id
            )
            console.log(tasksWithoutDeletedTask)
            return tasksWithoutDeletedTask
          })
        },
      })
    

  2. First, provide a query key to your useQuery call (https://tanstack.com/query/latest/docs/react/guides/query-keys).

    Then in the onSuccess of your mutation, you’ll invalidate that query key, which will essentially cause React Query to re-fetch the data for you (https://tanstack.com/query/latest/docs/react/guides/query-invalidation).

    For example:

    const { data: sessionData } = useSession()
    
    const {
      data: tasks,
      refetch: refetchTasks,
    } = api.task.getAll.useQuery(["tasks"], {
      enabled: sessionData?.user !== undefined,
    })
    
    const queryClient = useQueryClient();
    
    const createTask = api.task.create.useMutation({
      onSuccess: () => {
        queryClient.invalidateQueries(["tasks"]);
      },
    })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search