This commit is contained in:
@@ -67,6 +67,14 @@ export const useUpdateCatalog = () => {
|
||||
mutationFn: api.updateCatalog,
|
||||
});
|
||||
|
||||
// Ref to always hold the latest mutation without adding it to useCallback/useEffect deps.
|
||||
// React Query's useMutation returns a new object reference on every render, so
|
||||
// closing over `mutation` directly would cause scheduleUpdate and the cleanup effect
|
||||
// to be recreated/re-run on every render — firing mutation.mutate on each re-render
|
||||
// during drag (potentially 100+ times).
|
||||
const mutationRef = useRef(mutation);
|
||||
mutationRef.current = mutation;
|
||||
|
||||
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const pendingParamsRef = useRef<
|
||||
Parameters<typeof api.updateCatalog>[0] | null
|
||||
@@ -96,11 +104,11 @@ export const useUpdateCatalog = () => {
|
||||
pendingParamsRef.current = null;
|
||||
setIsScheduledSaving(false);
|
||||
if (pendingParams) {
|
||||
mutation.mutate(pendingParams);
|
||||
mutationRef.current.mutate(pendingParams);
|
||||
}
|
||||
}, delayMs);
|
||||
},
|
||||
[mutation],
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(
|
||||
@@ -112,12 +120,12 @@ export const useUpdateCatalog = () => {
|
||||
// اگر کاربر قبل از پایان debounce از ادیتور خارج شد،
|
||||
// آخرین تغییرات معلق را همان لحظه ذخیره کن.
|
||||
if (pendingParamsRef.current) {
|
||||
mutation.mutate(pendingParamsRef.current);
|
||||
mutationRef.current.mutate(pendingParamsRef.current);
|
||||
pendingParamsRef.current = null;
|
||||
}
|
||||
setIsScheduledSaving(false);
|
||||
},
|
||||
[mutation],
|
||||
[],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -64,11 +64,7 @@ const AbstractShape = ({ obj, isSelected, onSelect, onUpdate, draggable }: Shape
|
||||
}
|
||||
}}
|
||||
onDragMove={(e) => {
|
||||
const node = e.target;
|
||||
onUpdate(obj.id, {
|
||||
x: node.x() - (obj.width || 100) / 2,
|
||||
y: node.y() - (obj.height || 100) / 2,
|
||||
});
|
||||
e.target.getLayer()?.batchDraw();
|
||||
}}
|
||||
onDragEnd={(e) => {
|
||||
const node = e.target;
|
||||
|
||||
@@ -53,11 +53,7 @@ const CircleShape = ({ obj, isSelected, onSelect, onUpdate, draggable }: ShapePr
|
||||
}
|
||||
}}
|
||||
onDragMove={(e) => {
|
||||
const node = e.target;
|
||||
onUpdate(obj.id, {
|
||||
x: node.x(),
|
||||
y: node.y(),
|
||||
});
|
||||
e.target.getLayer()?.batchDraw();
|
||||
}}
|
||||
onDragEnd={(e) => {
|
||||
const node = e.target;
|
||||
|
||||
@@ -60,11 +60,7 @@ const TriangleShape = ({ obj, isSelected, onSelect, onUpdate, draggable }: Shape
|
||||
}
|
||||
}}
|
||||
onDragMove={(e) => {
|
||||
const node = e.target;
|
||||
onUpdate(obj.id, {
|
||||
x: node.x() - (obj.width || 100) / 2,
|
||||
y: node.y() - (obj.height || 100) / 2,
|
||||
});
|
||||
e.target.getLayer()?.batchDraw();
|
||||
}}
|
||||
onDragEnd={(e) => {
|
||||
const node = e.target;
|
||||
|
||||
Reference in New Issue
Block a user