Optimistic update
I'm encountering an issue where, upon updating the data, the response updates quickly with the new list but then reverts back to the old value after a few milliseconds, before finally returning to the new value. 
import { api } from "@/utils/api";
import type { Category } from "@prisma/client";
export const useMutationUpdateCategory = () => {
    const utils = api.useContext();
    return api.category.update.useMutation({
        onMutate: async (variables) => {
            // Cancel any outgoing refetches (so they don't overwrite(race condition) our optimistic update)
            await utils.category.list.cancel();
            const previousQueryData = utils.category.list.getData();
            const newCategory: Category = {
                id: crypto.randomUUID(),
                name: variables.name,
                slug: variables.name,
                createdAt: new Date(),
                updatedAt: new Date(),
            };
            utils.category.list.setData(undefined, (oldQueryData) => {
                if (oldQueryData) {
                    const filteredData =
                        oldQueryData.filter((item) => item.slug !== variables.slug) ?? [];
                    const elementIndex =
                        oldQueryData.findIndex((item) => item.slug === variables.slug) ??
                        -1;
                    filteredData.splice(elementIndex, 0, newCategory);
                    return filteredData;
                }
            });
            // Return a function to be used in the onError callback
            return () => utils.category.list.setData(undefined, previousQueryData);
        },
        onError: (error, variables, rollback) => {
            // If there is an error, rollback the mutation
            if (rollback) {
                rollback();
            }
        },
        onSettled: async (data, variables, context) => {
            await utils.category.list.invalidate();
        },
    });
};
import { api } from "@/utils/api";
import type { Category } from "@prisma/client";
export const useMutationUpdateCategory = () => {
    const utils = api.useContext();
    return api.category.update.useMutation({
        onMutate: async (variables) => {
            // Cancel any outgoing refetches (so they don't overwrite(race condition) our optimistic update)
            await utils.category.list.cancel();
            const previousQueryData = utils.category.list.getData();
            const newCategory: Category = {
                id: crypto.randomUUID(),
                name: variables.name,
                slug: variables.name,
                createdAt: new Date(),
                updatedAt: new Date(),
            };
            utils.category.list.setData(undefined, (oldQueryData) => {
                if (oldQueryData) {
                    const filteredData =
                        oldQueryData.filter((item) => item.slug !== variables.slug) ?? [];
                    const elementIndex =
                        oldQueryData.findIndex((item) => item.slug === variables.slug) ??
                        -1;
                    filteredData.splice(elementIndex, 0, newCategory);
                    return filteredData;
                }
            });
            // Return a function to be used in the onError callback
            return () => utils.category.list.setData(undefined, previousQueryData);
        },
        onError: (error, variables, rollback) => {
            // If there is an error, rollback the mutation
            if (rollback) {
                rollback();
            }
        },
        onSettled: async (data, variables, context) => {
            await utils.category.list.invalidate();
        },
    });
};
0 Replies