Skip to content

fix(client): remove useNavigate from AuthKitProvider to avoid SSR warning#59

Open
nicknisi wants to merge 1 commit into
mainfrom
fix/issue-57
Open

fix(client): remove useNavigate from AuthKitProvider to avoid SSR warning#59
nicknisi wants to merge 1 commit into
mainfrom
fix/issue-57

Conversation

@nicknisi
Copy link
Copy Markdown
Member

Summary

AuthKitProvider called useNavigate() unconditionally at the top of the component body. During SSR with TanStack Start, the Wrap component renders before RouterProvider context is established, causing repeated useRouter must be used inside a <RouterProvider> console warnings.

This PR removes useNavigate entirely from AuthKitProvider. The handleSignOut fallback navigation now uses window.location.href assignment instead of TanStack Router's navigate(), which is safe since sign-out is always a user-triggered client-side action.

Changes

  • src/client/AuthKitProvider.tsx: Removed useNavigate import and hook call. Replaced navigate({ to: returnTo }) with window.location.href = returnTo in the handleSignOut fallback path.
  • src/client/AuthKitProvider.spec.tsx: Removed global @tanstack/react-router mock. Added regression test that renders AuthKitProvider without RouterProvider context (would throw if useNavigate() were still called unconditionally). Updated sign-out tests to verify window.location.href assignment.

Closes #57

What was tested

Automated (176 tests pass):

  • All 16 AuthKitProvider.spec.tsx tests pass, including the new regression test "renders without router context (no useNavigate SSR warning)"
  • pnpm build succeeds with no type errors
  • No useNavigate references remain in source or built dist/client/ output
  • No @tanstack/react-router imports in dist/client/ output

Manual (Playwright E2E):

  • Started example app on localhost:3000
  • Navigated to home page and account page
  • Console output: 0 warnings (only a harmless favicon 404)
  • No useRouter must be used inside a <RouterProvider> warning observed

Manual reproduction steps

To reproduce the bug on main:

  1. Check out main and run pnpm install && pnpm build
  2. cd example && pnpm dev
  3. Open http://localhost:3000 in a browser with DevTools console open
  4. Observe: Repeated useRouter must be used inside a <RouterProvider> warnings in the console during SSR/hydration

To verify the fix on this branch:

  1. Check out fix/issue-57 and run pnpm install && pnpm build
  2. cd example && pnpm dev
  3. Open http://localhost:3000 in a browser with DevTools console open
  4. Observe: No useRouter warnings in the console

Verification

verified-no-warnings.png

Follow-ups

  • @tanstack/react-router remains in peerDependencies even though the client bundle no longer imports it. This is correct since server files (src/server/) still use redirect from that package. No action needed.

Copy link
Copy Markdown
Member Author

@nicknisi nicknisi left a comment

Choose a reason for hiding this comment

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

Reviewer note (info): @tanstack/react-router remains in peerDependencies even though the client bundle no longer imports it. This is correct -- server files in src/server/ still use redirect from @tanstack/react-router. No action needed.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 15, 2026

Greptile Summary

Removes the unconditional useNavigate() call from AuthKitProvider that was firing before RouterProvider was mounted during SSR with TanStack Start, causing repeated console warnings. The fallback navigation path in handleSignOut (used only when no active auth session exists) now assigns window.location.href directly, which is safe since sign-out is always a client-side, user-triggered action.

  • AuthKitProvider.tsx: useNavigate import and hook call removed; handleSignOut fallback changed from navigate({ to: returnTo }) to window.location.href = returnTo; useCallback dependency array simplified to [].
  • AuthKitProvider.spec.tsx: Global router mock removed; regression test added that would fail if useNavigate were called unconditionally; two sign-out tests updated to assert on window.location.href.

Confidence Score: 5/5

Safe to merge — the change is minimal, correctly targeted, and backed by a dedicated regression test.

The removal of useNavigate is confined to a single call site, the replacement (window.location.href) is appropriate for a client-only, user-triggered action, and the regression test will catch any future re-introduction of the unconditional hook call. No logic that affects auth state, session management, or redirects with an active session was changed.

No files require special attention.

Important Files Changed

Filename Overview
src/client/AuthKitProvider.tsx Removed useNavigate hook call and import; replaced navigate({ to: returnTo }) with window.location.href = returnTo in the null-URL branch of handleSignOut. useCallback deps array correctly simplified to [].
src/client/AuthKitProvider.spec.tsx Dropped global @tanstack/react-router mock; added regression test that renders AuthKitProvider without a RouterProvider to guard against useNavigate re-introduction; updated two sign-out tests to assert window.location.href instead of a mock navigate call.

Sequence Diagram

sequenceDiagram
    participant SSR as SSR / Wrap
    participant AKP as AuthKitProvider
    participant GSU as getSignOutUrl
    participant Win as window.location

    SSR->>AKP: render (no RouterProvider yet)
    Note over AKP: ✅ No useNavigate() call during render

    Note over AKP: User triggers sign-out
    AKP->>GSU: "getSignOutUrl({ data: { returnTo } })"
    alt result.url present (active session)
        GSU-->>AKP: "{ url: "https://auth.workos.com/logout" }"
        AKP->>Win: "window.location.href = result.url"
    else result.url is null (no session)
        GSU-->>AKP: "{ url: null }"
        AKP->>Win: "window.location.href = returnTo"
    end
Loading

Reviews (3): Last reviewed commit: "fix(client): remove useNavigate from Aut..." | Re-trigger Greptile

…ning

AuthKitProvider is rendered as a Wrap component before RouterProvider context exists. Calling useNavigate() unconditionally during render triggered "useRouter must be used inside a <RouterProvider>" warnings.

The navigate function was only used as a fallback in handleSignOut when no sign-out URL was returned. Replace it with window.location.href, which is appropriate for post-sign-out redirects (full page reload is desirable after session termination).

Fixes #57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant