Fix toast accept button: instant feedback + double-click guard
Toast buttons are static Sonner elements that can't bind React state, so clicks had no visual feedback and allowed duplicate mutations. Now: dismiss custom toast immediately, show loading toast, and block concurrent clicks via a ref-based Set guard. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
60281caa64
commit
dff36f30c8
@ -14,16 +14,30 @@ export default function NotificationToaster() {
|
|||||||
const maxSeenIdRef = useRef(0);
|
const maxSeenIdRef = useRef(0);
|
||||||
const initializedRef = useRef(false);
|
const initializedRef = useRef(false);
|
||||||
const prevUnreadRef = useRef(0);
|
const prevUnreadRef = useRef(0);
|
||||||
|
// Track in-flight request IDs so repeated clicks are blocked
|
||||||
|
const respondingRef = useRef<Set<number>>(new Set());
|
||||||
|
|
||||||
const handleConnectionRespond = useCallback(
|
const handleConnectionRespond = useCallback(
|
||||||
async (requestId: number, action: 'accept' | 'reject', toastId: string | number) => {
|
async (requestId: number, action: 'accept' | 'reject', toastId: string | number) => {
|
||||||
|
// Guard against double-clicks (Sonner toasts are static, no disabled prop)
|
||||||
|
if (respondingRef.current.has(requestId)) return;
|
||||||
|
respondingRef.current.add(requestId);
|
||||||
|
|
||||||
|
// Immediately dismiss the custom toast and show a loading indicator
|
||||||
|
toast.dismiss(toastId);
|
||||||
|
const loadingId = toast.loading(
|
||||||
|
action === 'accept' ? 'Accepting connection…' : 'Declining request…',
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await respond({ requestId, action });
|
await respond({ requestId, action });
|
||||||
// onSuccess in useConnections already dismisses the custom toast and invalidates caches
|
toast.dismiss(loadingId);
|
||||||
toast.success(action === 'accept' ? 'Connection accepted' : 'Request declined');
|
toast.success(action === 'accept' ? 'Connection accepted' : 'Request declined');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toast.dismiss(toastId);
|
toast.dismiss(loadingId);
|
||||||
toast.error(getErrorMessage(err, 'Failed to respond to request'));
|
toast.error(getErrorMessage(err, 'Failed to respond to request'));
|
||||||
|
} finally {
|
||||||
|
respondingRef.current.delete(requestId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[respond],
|
[respond],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user