Unify toast accept path with notification center via useConnections

Toast now uses the same respond() from useConnections hook instead
of raw api.put, making both accept surfaces share identical code.
Also made respondMutation.onSuccess fire-and-forget to prevent
invalidation errors from surfacing as mutation failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Kyle 2026-03-04 10:30:35 +08:00
parent 5828bbf8e2
commit 60281caa64
2 changed files with 12 additions and 16 deletions

View File

@ -3,11 +3,13 @@ import { toast } from 'sonner';
import { Check, X, Bell, UserPlus } from 'lucide-react';
import { useQueryClient } from '@tanstack/react-query';
import { useNotifications } from '@/hooks/useNotifications';
import api, { getErrorMessage } from '@/lib/api';
import { useConnections } from '@/hooks/useConnections';
import { getErrorMessage } from '@/lib/api';
import type { AppNotification } from '@/types';
export default function NotificationToaster() {
const { notifications, unreadCount } = useNotifications();
const { respond } = useConnections();
const queryClient = useQueryClient();
const maxSeenIdRef = useRef(0);
const initializedRef = useRef(false);
@ -16,20 +18,15 @@ export default function NotificationToaster() {
const handleConnectionRespond = useCallback(
async (requestId: number, action: 'accept' | 'reject', toastId: string | number) => {
try {
await api.put(`/connections/requests/${requestId}/respond`, { action });
await respond({ requestId, action });
// onSuccess in useConnections already dismisses the custom toast and invalidates caches
toast.success(action === 'accept' ? 'Connection accepted' : 'Request declined');
} catch (err) {
toast.dismiss(toastId);
toast.error(getErrorMessage(err, 'Failed to respond to request'));
return;
}
toast.dismiss(toastId);
toast.success(action === 'accept' ? 'Connection accepted' : 'Request declined');
// Fire-and-forget — invalidation errors should not surface as "Failed to respond"
queryClient.invalidateQueries({ queryKey: ['connections'] });
queryClient.invalidateQueries({ queryKey: ['people'] });
queryClient.invalidateQueries({ queryKey: ['notifications'] });
},
[queryClient],
[respond],
);
// Track unread count changes to force-refetch the list

View File

@ -57,14 +57,13 @@ export function useConnections() {
const { data } = await api.put(`/connections/requests/${requestId}/respond`, { action });
return data;
},
onSuccess: async (_, variables) => {
onSuccess: (_, variables) => {
// Dismiss any lingering Sonner toast for this request
toast.dismiss(`connection-request-${variables.requestId}`);
await Promise.all([
queryClient.invalidateQueries({ queryKey: ['connections'] }),
queryClient.invalidateQueries({ queryKey: ['people'] }),
queryClient.invalidateQueries({ queryKey: ['notifications'] }),
]);
// Fire-and-forget — errors here must not surface as mutation failures
queryClient.invalidateQueries({ queryKey: ['connections'] });
queryClient.invalidateQueries({ queryKey: ['people'] });
queryClient.invalidateQueries({ queryKey: ['notifications'] });
},
});