fix: prevent returning the previous route data on route transition (#646)

Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
This commit is contained in:
Valerio Ageno
2025-03-15 11:42:34 +01:00
committed by GitHub
parent bfd0041c6a
commit 1c45b29ed1
2 changed files with 57 additions and 15 deletions
@@ -7,14 +7,11 @@ import { useServerPayloadData } from '../hooks/useServerPayloadData'
import { RouteMatch } from './RouteMatch' import { RouteMatch } from './RouteMatch'
function createRouteComponent( function createRouteComponent(routeType: string): RouteComponent {
routeType: string,
includeChildren: boolean,
): RouteComponent {
const RootComponent = (({ children }: RouteProps) => ( const RootComponent = (({ children }: RouteProps) => (
<div data-testid={routeType}> <div data-testid={routeType}>
{`${routeType} route`} {`${routeType} route`}
{includeChildren ? children : null} {children}
</div> </div>
)) as RouteComponent )) as RouteComponent
RootComponent.preload = vi.fn() RootComponent.preload = vi.fn()
@@ -22,33 +19,45 @@ function createRouteComponent(
return RootComponent return RootComponent
} }
function createLeafRouteComponent(routeType: string): RouteComponent {
const RootComponent = (({ data }: RouteProps) => (
<div data-testid={routeType}>{data ? JSON.stringify(data) : null}</div>
)) as RouteComponent
RootComponent.preload = vi.fn()
RootComponent.displayName = routeType
return RootComponent
}
const root = new Route({ const root = new Route({
isRoot: true, isRoot: true,
component: createRouteComponent('root', true), component: createRouteComponent('root'),
}) })
const parent = new Route({ const parent = new Route({
component: createRouteComponent('parent', true), component: createRouteComponent('parent'),
getParentRoute: (): Route => root, getParentRoute: (): Route => root,
}) })
const route = new Route({ const route = new Route({
component: createRouteComponent('current', false), component: createLeafRouteComponent('current'),
getParentRoute: (): Route => parent, getParentRoute: (): Route => parent,
}) })
vi.mock('../hooks/useServerPayloadData', () => ({ vi.mock('../hooks/useServerPayloadData', () => ({
useServerPayloadData: vi.fn(), useServerPayloadData: vi.fn(),
})) }))
vi.mocked(useServerPayloadData).mockReturnValue({
data: undefined, const useServerPayloadDataMock = vi.mocked(useServerPayloadData)
isLoading: false,
})
describe('<RouteMatch />', () => { describe('<RouteMatch />', () => {
afterEach(cleanup) afterEach(cleanup)
it('should correctly render nested routes', () => { it('should correctly render nested routes', () => {
useServerPayloadDataMock.mockReturnValue({
data: { some: 'data' },
isLoading: false,
})
render(<RouteMatch route={route} serverInitialData={{}} />) render(<RouteMatch route={route} serverInitialData={{}} />)
expect(screen.getByTestId('root')).toMatchInlineSnapshot( expect(screen.getByTestId('root')).toMatchInlineSnapshot(
@@ -64,11 +73,38 @@ describe('<RouteMatch />', () => {
<div <div
data-testid="current" data-testid="current"
> >
current route {"some":"data"}
</div> </div>
</div> </div>
</div> </div>
`, `,
) )
}) })
it('should return null data when while loading', () => {
useServerPayloadDataMock.mockReturnValue({
data: { some: 'data' },
isLoading: true,
})
render(<RouteMatch route={route} serverInitialData={{}} />)
expect(screen.getByTestId('root')).toMatchInlineSnapshot(
`
<div
data-testid="root"
>
root route
<div
data-testid="parent"
>
parent route
<div
data-testid="current"
/>
</div>
</div>
`,
)
})
}) })
@@ -24,10 +24,16 @@ export const RouteMatch = ({
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
const routes = useMemo(() => loadParentComponents(route), [route.id]) const routes = useMemo(() => loadParentComponents(route), [route.id])
const routeData = isLoading ? null : data
return ( return (
<TraverseRootComponents routes={routes} data={data} isLoading={isLoading}> <TraverseRootComponents
routes={routes}
data={routeData}
isLoading={isLoading}
>
<Suspense> <Suspense>
<route.component data={data} isLoading={isLoading} /> <route.component data={routeData} isLoading={isLoading} />
</Suspense> </Suspense>
</TraverseRootComponents> </TraverseRootComponents>
) )