router icon indicating copy to clipboard operation
router copied to clipboard

Router's context doesn't have injected values on initial render from login callback

Open jwtong opened this issue 1 year ago • 6 comments

Describe the bug

import {
  Auth0ContextInterface,
  Auth0Provider,
  useAuth0,
  User
} from '@auth0/auth0-react'

import { createRouter, RouterProvider } from '@tanstack/react-router'

import { SettingsProvider } from './providers/SettingsProvider'
import { TrpcQueryProvider } from './providers/TrpcQueryProvider'
import { routeTree } from './routeTree.gen'
import { trpc } from './utils/trpc'

export interface MyRouteContext {
  auth: Auth0ContextInterface<User>
  trpcUtils: ReturnType<typeof trpc.useUtils>
}

// Set up a Router instance
const myRouter = createRouter({
  routeTree,
  defaultPreload: 'intent',
  defaultPreloadStaleTime: 0,
  context: {
    auth: undefined!,
    trpcUtils: undefined!
  }
})

// Register things for typesafety
declare module '@tanstack/react-router' {
  interface Register {
    router: typeof myRouter
  }
}

export default function App() {
  return (
    <SettingsProvider>
      <Auth0Provider
        domain={import.meta.env.VITE_AUTH0_DOMAIN!}
        clientId={import.meta.env.VITE_AUTH0_CLIENT_ID!}
        authorizationParams={{
          redirect_uri:
            typeof window !== 'undefined' ? window.location.origin : '',
          audience: import.meta.env.VITE_AUTH0_AUDIENCE!
        }}
        cacheLocation='localstorage'
        onRedirectCallback={(appState) => {
          myRouter.navigate(appState?.navigateTo! || { to: '/' })
        }}>
        <TrpcQueryProvider>
          <RouterWithContext router={myRouter} />
        </TrpcQueryProvider>
      </Auth0Provider>
    </SettingsProvider>
  )
}

function RouterWithContext({ router }: { router: typeof myRouter }) {
  const auth = useAuth0()
  const trpcUtils = trpc.useUtils()
  if (auth.isLoading) {
    return null
  }

  return <RouterProvider router={router} context={{ auth, trpcUtils }} />
}

When the auth0 provider fires the onRedirectCallback(), the initial navigation results in a load/preload that doesn't contain auth or trpcUtils.

Your Example Website or App

https://add-ndmoby1i3-add-wrk.vercel.app/

Steps to Reproduce the Bug or Issue

  1. Click on Dashboard
  2. Signup as new user
  3. See redirect on auth0 login doesn't provide correct context

Expected behavior

As a user, i always expect my router context to contain the injected values, given the way I've declared RouterWithContext

Screenshots or Videos

No response

Platform

  • OS: [e.g. macOS, Windows, Linux]
  • Browser: [e.g. Chrome, Safari, Firefox]
  • Version: [e.g. 91.1]

Additional context

No response

jwtong avatar Aug 27 '24 02:08 jwtong

Screenshot 2024-08-26 at 7 10 04 PM

jwtong avatar Aug 27 '24 02:08 jwtong

Screenshot 2024-08-26 at 7 17 49 PM

jwtong avatar Aug 27 '24 02:08 jwtong

export const Route = createFileRoute('/dashboard')({
  beforeLoad: ({ context, location }) => {
    if (context.auth && !context.auth.isAuthenticated) {
      context.auth.loginWithRedirect({
        appState: { navigateTo: location }
      })
    }
  },
  loader: async ({ context }) => {
    const data =
      await context.trpcUtils?.customCompany.getMyMemberCompanies.ensureData({})
  },
  component: DashboardPage
})

Checking for undefined works. Note the beforeLoad() and loader() fire twice after the onRedirectCallback()

jwtong avatar Aug 27 '24 02:08 jwtong

Please attach a reproduction of the problem you are facing.

SeanCassiere avatar Aug 27 '24 04:08 SeanCassiere

See https://discord.com/channels/719702312431386674/1278074925399408641, if this is related to the problem you are facing.

SeanCassiere avatar Aug 27 '24 21:08 SeanCassiere

@SeanCassiere Yes, that's the same issue! looks like the thread is still unresolved at the end.

jwtong avatar Aug 27 '24 22:08 jwtong