React Query mutating individual items in table by switch buttons rapidly causes buttons to turning off and on again and affecting each other

47 Views Asked by At

I'm using optimistic query to update the table

const update = async (values: UpdateRequest) => {
  const { data } = await axios.post(
    `${update}`,
    {
      ...values,
    }
  );
  return data;
};

export const useUpdate = (): UseMutationResult<
  MutationResponse,
  Error,
  UpdateRequest,
  { previousData: Query }
> => {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (values) => updateAlert(values),
    // When mutate is called:
    onMutate: async (values: UpdateRequest) => {
      // Cancel any outgoing refetches
      // (so they don't overwrite our optimistic update)

      await queryClient.cancelQueries({
        queryKey: [queryKey],
      });

      // Snapshot the previous value
      const previousData = queryClient.getQueryData<Query>([
        queryKey,
      ]);

      // Optimistically update the data
      queryClient.setQueryData<GetAlertsResponse>(
        [queryKey],
        (oldData) => {
          const newData = oldData.item.map((item) => {
            if (item.id === values.id) {
              return {
                ...item,
                ...values,
              };
            }
            return item;
          });

          return { item: newData };
        }
      );

      // Return a context object with the snapshotted value
      return { previousData };
    },
    // If the mutation fails,
    // use the context returned from onMutate to roll back
    onError: (err, values, context) => {
      queryClient.setQueryData([queryKey], context.previousAlerts);
    },

    // Always refetch after error or success:
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: [queryKey] });
    },
  });
};

export default useUpdate;

and have a column with switch button

const SwitchRenderer: FC<ValueFormatterParams<AlertType>> = (params) => {
  const { value, data } = params;
  const { mutate } = useUpdate();

  const handleCheckedChange = (checked: boolean) => {
    mutate({ is_enabled: checked, id: data.id});
  };
  return (
      <SwitchComponent checked={value} onCheckedChange={handleCheckedChange} />
  );
};

When a rapidly change different items switch keys they are affecting their state and making them different than I desired at first. When I clicked the second one first one turning off for example. Also they are turning off and on again (flashes). Also if I clicked just one switch repeatedly and rapidly at the and it flashes also.

I tried debouncing but didn't work. With debouncing I tried to disable the switch button until the mutation is done but didn't solve. I also tried the solutions in this answer https://stackoverflow.com/a/72374013/11633296 but didn't work also.

My guess is saving all the mutation requests until done then doing all off them after all settled and then invalidating queries. For this I need to create a promise stack and listen this at the optimistic query. But I'm not sure how to do this.

0

There are 0 best solutions below