0

I'm developing a todo app using TRPC+Prisma+NextJS

Right now, the app shows a list of todos stored in database.

I'd like to optimistically update the state of the todo (finish / pending)

Right now, I can apply the optimistic update creating a new object from the original one with this code:

const newmap = JSON.parse(JSON.stringify(prevData));

newmap.map((el) => {
    if(el.id === el.completed = completed;
}
  return el
})

ctx.todos.getAll.setData(undefined, newmap )

The question is if a can make it more simple.

Reading React Query documentation I think it should be possible filtering the todos cached by id:

useMutation({
  mutationFn: updateTodo,
  // When mutate is called:
  onMutate: async (newTodo) => {
    // Cancel any outgoing refetches
    // (so they don't overwrite our optimistic update)
    await queryClient.cancelQueries({ queryKey: ['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 }
  },

I tried to replicate this using TRPC helpers methods (getData) but I cannot filter the list of todos

Is it possible to change one todo from the list of stored todos in cache?

Thanks!

JaB
  • 310
  • 4
  • 15

1 Answers1

0

This can be done by using tRPC's useContext. In tRPC, most of the operations you would do using the Query Client in React Query can be done using useContext, which is effectively a typesafe wrapper around it. My example code just toggles the completed field given an ID, but it should give you an idea of how to implement your optimistic update.

const utils = api.useContext();
const todos = api.useless.todos.useQuery();
const complete = api.useless.complete.useMutation({
  onMutate: async ({ id }) => {
    await utils.useless.todos.cancel();
    utils.useless.todos.setData(undefined, (old) => {
      return old?.map((todo) => {
        if (todo.id === id) {
          return {
            ...todo,
            completed: !todo.completed,
          };
        }
        return todo;
      });
    });
  },
  onSettled: () => todos.refetch(),
});