فهرست منبع

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 ماه پیش
والد
کامیت
e8f0698ae1
4فایلهای تغییر یافته به همراه17 افزوده شده و 3 حذف شده
  1. 0 0
      CHANGELOG.md
  2. 16 2
      frontend/src/components/LocalProfilesView.tsx
  3. 0 0
      static/assets/index-D8RZYXPJ.js
  4. 1 1
      static/index.html

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
CHANGELOG.md


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

@@ -15,7 +15,7 @@ import {
   AlertCircle,
   AlertCircle,
 } from 'lucide-react';
 } from 'lucide-react';
 import { api } from '../api/client';
 import { api } from '../api/client';
-import type { LocalPreset } from '../api/client';
+import type { LocalPreset, LocalPresetsResponse } from '../api/client';
 import { Card, CardContent } from './Card';
 import { Card, CardContent } from './Card';
 import { Button } from './Button';
 import { Button } from './Button';
 import { useToast } from '../contexts/ToastContext';
 import { useToast } from '../contexts/ToastContext';
@@ -276,7 +276,21 @@ export function LocalProfilesView() {
 
 
   const deleteMutation = useMutation({
   const deleteMutation = useMutation({
     mutationFn: (id: number) => api.deleteLocalPreset(id),
     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'] });
       queryClient.invalidateQueries({ queryKey: ['localPresets'] });
       // Match the import path: the SliceModal's `slicerPresets` query needs
       // Match the import path: the SliceModal's `slicerPresets` query needs
       // to be invalidated too, otherwise the deleted preset keeps appearing
       // to be invalidated too, otherwise the deleted preset keeps appearing

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
static/assets/index-D8RZYXPJ.js


+ 1 - 1
static/index.html

@@ -26,7 +26,7 @@
 
 
     <!-- Splash screens for iOS -->
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-D1CwWWEy.js"></script>
+    <script type="module" crossorigin src="/assets/index-D8RZYXPJ.js"></script>
     <link rel="stylesheet" crossorigin href="/assets/index-Deb9qzJl.css">
     <link rel="stylesheet" crossorigin href="/assets/index-Deb9qzJl.css">
   </head>
   </head>
   <body>
   <body>

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است