@@ -3125,4 +3125,87 @@ describe('useRouteContext in the component', () => {
31253125
31263126 expect ( content ) . toBeInTheDocument ( )
31273127 } )
3128- } )
3128+
3129+ test ( "reproducer #4998 - on navigate (with preload), route component isn't rendered with undefined context if beforeLoad is pending" , async ( ) => {
3130+ const beforeLoad = vi . fn ( )
3131+ const select = vi . fn ( )
3132+ let resolved = 0
3133+ const rootRoute = createRootRoute ( )
3134+ const indexRoute = createRoute ( {
3135+ getParentRoute : ( ) => rootRoute ,
3136+ path : '/' ,
3137+ component : ( ) => < Link to = "/foo" > To foo</ Link > ,
3138+ } )
3139+ const fooRoute = createRoute ( {
3140+ getParentRoute : ( ) => rootRoute ,
3141+ path : '/foo' ,
3142+ beforeLoad : async ( ...args ) => {
3143+ beforeLoad ( ...args )
3144+ await sleep ( WAIT_TIME )
3145+ resolved += 1
3146+ return { foo : resolved }
3147+ } ,
3148+ component : ( ) => {
3149+ fooRoute . useRouteContext ( { select } )
3150+ return < h1 > Foo index page</ h1 >
3151+ } ,
3152+ pendingComponent : ( ) => 'loading' ,
3153+ } )
3154+ const routeTree = rootRoute . addChildren ( [
3155+ indexRoute ,
3156+ fooRoute
3157+ ] )
3158+ const router = createRouter ( {
3159+ routeTree,
3160+ history,
3161+ defaultPreload : 'intent' ,
3162+ defaultPendingMs : 0 ,
3163+ } )
3164+
3165+ render ( < RouterProvider router = { router } /> )
3166+ const linkToFoo = await screen . findByText ( 'To foo' )
3167+
3168+ fireEvent . focus ( linkToFoo )
3169+ expect ( beforeLoad ) . toHaveBeenCalledTimes ( 1 )
3170+ expect ( resolved ) . toBe ( 0 )
3171+
3172+ await sleep ( WAIT_TIME )
3173+
3174+ expect ( beforeLoad ) . toHaveBeenCalledTimes ( 1 )
3175+ expect ( resolved ) . toBe ( 1 )
3176+ expect ( beforeLoad ) . toHaveBeenNthCalledWith ( 1 , expect . objectContaining ( {
3177+ cause : 'preload' ,
3178+ preload : true ,
3179+ } ) )
3180+
3181+ expect ( select ) . not . toHaveBeenCalled ( )
3182+
3183+ fireEvent . click ( linkToFoo )
3184+ expect ( beforeLoad ) . toHaveBeenCalledTimes ( 2 )
3185+ expect ( resolved ) . toBe ( 1 )
3186+
3187+ await screen . findByText ( 'Foo index page' )
3188+
3189+ expect ( beforeLoad ) . toHaveBeenCalledTimes ( 2 )
3190+ expect ( beforeLoad ) . toHaveBeenNthCalledWith ( 2 , expect . objectContaining ( {
3191+ cause : 'enter' ,
3192+ preload : false ,
3193+ } ) )
3194+ expect ( select ) . toHaveBeenNthCalledWith ( 1 , expect . objectContaining ( {
3195+ foo : 1 ,
3196+ } ) )
3197+ expect ( select ) . not . toHaveBeenCalledWith ( { } )
3198+
3199+ await sleep ( WAIT_TIME )
3200+ expect ( beforeLoad ) . toHaveBeenCalledTimes ( 2 )
3201+ expect ( resolved ) . toBe ( 2 )
3202+
3203+ // ensure the context has been updated once the beforeLoad has resolved
3204+ expect ( select ) . toHaveBeenLastCalledWith ( expect . objectContaining ( {
3205+ foo : 2 ,
3206+ } ) )
3207+
3208+ // the route component will be rendered multiple times, ensure it always has the context
3209+ expect ( select ) . not . toHaveBeenCalledWith ( { } )
3210+ } )
3211+ } )
0 commit comments