Просмотр исходного кода

fix(local-presets): optimistic remove on delete

      The Slicer -> Local Profiles page kept showing a just-deleted row for
      the ~hundreds of ms it took invalidateQueries to refetch. A quick
      re-click on the same row opened a second delete-confirm modal that
      resolved to a 404 from the backend.

      Add an optimistic queryClient.setQueryData filter in deleteMutation's
      onSuccess so the row disappears the instant the DELETE returns 200.
      Existing invalidateQueries calls stay in place to reconcile any drift.

      Found while reproducing #1713 (verifying maziggy's setup against the
      reporter's). Unrelated to that investigation but caught here.
maziggy 2 месяцев назад
Родитель
Сommit
0eed98657f
2 измененных файлов с 16 добавлено и 2 удалено
  1. 0 0
      CHANGELOG.md
  2. 16 2
      frontend/src/components/LocalProfilesView.tsx

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
CHANGELOG.md


+ 16 - 2
frontend/src/components/LocalProfilesView.tsx

@@ -15,7 +15,7 @@ import {
   AlertCircle,
 } from 'lucide-react';
 import { api } from '../api/client';
-import type { LocalPreset } from '../api/client';
+import type { LocalPreset, LocalPresetsResponse } from '../api/client';
 import { Card, CardContent } from './Card';
 import { Button } from './Button';
 import { useToast } from '../contexts/ToastContext';
@@ -276,7 +276,21 @@ export function LocalProfilesView() {
 
   const deleteMutation = useMutation({
     mutationFn: (id: number) => api.deleteLocalPreset(id),
-    onSuccess: () => {
+    onSuccess: (_, id) => {
+      // Optimistically drop the row from the cached list so the rendered table
+      // updates the instant the DELETE returns. Without this the row stays
+      // visible until invalidateQueries' background refetch completes, and a
+      // quick re-click on the same row opens a second delete-confirm modal
+      // that resolves to a 404 (server already deleted it). The cache holds a
+      // grouped response (filament / printer / process), not a flat list.
+      queryClient.setQueryData<LocalPresetsResponse>(['localPresets'], (old) => {
+        if (!old) return old;
+        return {
+          filament: old.filament.filter((p) => p.id !== id),
+          printer: old.printer.filter((p) => p.id !== id),
+          process: old.process.filter((p) => p.id !== id),
+        };
+      });
       queryClient.invalidateQueries({ queryKey: ['localPresets'] });
       // Match the import path: the SliceModal's `slicerPresets` query needs
       // to be invalidated too, otherwise the deleted preset keeps appearing

Некоторые файлы не были показаны из-за большого количества измененных файлов