Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/components/layout/UserMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Logout03Icon, Share01Icon, UserIcon } from '@hugeicons/core-free-icons';
import { HugeiconsIcon } from '@hugeicons/react';
import { Link } from '@tanstack/react-router';
import { Link, useNavigate } from '@tanstack/react-router';
import { motion } from 'framer-motion';
import {
DropdownMenu,
Expand All @@ -25,6 +25,8 @@ interface UserMenuProps {
export function UserMenu({ user }: UserMenuProps) {
const { ref, position } = useMagnetic(0.2);

const navigate = useNavigate();

return (
<DropdownMenu>
<motion.div
Expand Down Expand Up @@ -73,7 +75,13 @@ export function UserMenu({ user }: UserMenuProps) {
<DropdownMenuSeparator />
<DropdownMenuItem
className="font-mono text-xs font-bold tracking-widest uppercase text-destructive"
onClick={() => authClient.signOut()}
onClick={async () => {
await authClient.signOut({
fetchOptions: {
onSuccess: () => navigate({reloadDocument: true})
}
})
}}
>
Comment on lines 76 to 85
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

authClient.signOut() is likely async (it’s invoked with void elsewhere). With render={<Link to="/" />} the navigation may occur before sign-out completes, and any rejection from signOut() is currently unhandled. Consider handling the promise (e.g., void/await) and triggering navigation only after sign-out succeeds (using router navigation in the click handler rather than rendering as a Link), optionally showing an error if sign-out fails.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mellobacon Ignore the comment about async here, fire-and-forget is the typical pattern for async handlers in click events and because the AppHeader is always mounted, the navigation to / won't stop the signOut from continuing

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That being said, a better way to do this would be to use better-auth's fetchOptions so that the redirect is within the auth lifecycle

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

In our example here, we'd just use the useNavigate hook from tanstack router to await the nav to / in the success of fetchOptions

<HugeiconsIcon icon={Logout03Icon} size={14} />
SIGN OUT
Expand Down