Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
8 changes: 4 additions & 4 deletions packages/react-router/tests/useParams.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ test('useParams must return parsed result if applicable.', async () => {

expect(window.location.pathname).toBe('/posts/category_first')
expect(await screen.findByTestId('post-category-heading')).toBeInTheDocument()
expect(mockedfn).toHaveBeenCalledTimes(1)
expect(mockedfn).not.toHaveBeenCalled()

mockedfn.mockClear()
await act(() => fireEvent.click(firstPostLink))
Expand All @@ -213,7 +213,7 @@ test('useParams must return parsed result if applicable.', async () => {
expect(renderedPost.category).toBe('one')
expect(paramCategoryValue.textContent).toBe('one')
expect(paramPostIdValue.textContent).toBe('1')
expect(mockedfn).toHaveBeenCalledTimes(2)
expect(mockedfn).toHaveBeenCalledTimes(1)
expect(allCategoryLink).toBeInTheDocument()

mockedfn.mockClear()
Expand All @@ -224,7 +224,7 @@ test('useParams must return parsed result if applicable.', async () => {
expect(window.location.pathname).toBe('/posts/category_all')
expect(await screen.findByTestId('post-category-heading')).toBeInTheDocument()
expect(secondPostLink).toBeInTheDocument()
expect(mockedfn).toHaveBeenCalledTimes(2)
expect(mockedfn).not.toHaveBeenCalled()

mockedfn.mockClear()
await act(() => fireEvent.click(secondPostLink))
Expand All @@ -246,5 +246,5 @@ test('useParams must return parsed result if applicable.', async () => {
expect(renderedPost.category).toBe('two')
expect(paramCategoryValue.textContent).toBe('all')
expect(paramPostIdValue.textContent).toBe('2')
expect(mockedfn).toHaveBeenCalledTimes(2)
expect(mockedfn).toHaveBeenCalledTimes(1)
})
70 changes: 43 additions & 27 deletions packages/router-core/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1330,22 +1330,9 @@ export class RouterCore<
}
}

globalNotFoundRouteId = (() => {
if (!isGlobalNotFound) {
return undefined
}

if (this.options.notFoundMode !== 'root') {
for (let i = matchedRoutes.length - 1; i >= 0; i--) {
const route = matchedRoutes[i]!
if (route.children) {
return route.id
}
}
}

return rootRouteId
})()
globalNotFoundRouteId = isGlobalNotFound
? findGlobalNotFoundRouteId(this.options.notFoundMode, matchedRoutes)
: undefined
}

const matches: Array<AnyRouteMatch> = []
Expand Down Expand Up @@ -1775,16 +1762,30 @@ export class RouterCore<
params: nextParams,
}).interpolatedPath

const { matches: destMatches, rawParams } = this.matchRoutesInternal(
{ pathname: interpolatedNextTo } as ParsedLocation,
{ _buildLocation: true },
)
const destRoutes = destMatches.map(
(d) => this.looseRoutesById[d.routeId]!,
)

// Check if any match indicates global not found
const globalNotFoundMatch = destMatches.find((m) => m.globalNotFound)
// Use lightweight getMatchedRoutes instead of matchRoutesInternal
// This avoids creating full match objects (AbortController, ControlledPromise, etc.)
// which are expensive and not needed for buildLocation
const destMatchResult = this.getMatchedRoutes(interpolatedNextTo)
const destRoutes = destMatchResult.matchedRoutes as Array<AnyRoute>
const rawParams = destMatchResult.routeParams

// Compute globalNotFoundRouteId using the same logic as matchRoutesInternal
const isGlobalNotFound = destMatchResult.foundRoute
? destMatchResult.foundRoute.path !== '/' &&
destMatchResult.routeParams['**']
: trimPathRight(interpolatedNextTo)

let globalNotFoundRouteId: string | undefined
if (isGlobalNotFound) {
if (this.options.notFoundRoute) {
globalNotFoundRouteId = this.options.notFoundRoute.id
} else {
globalNotFoundRouteId = findGlobalNotFoundRouteId(
this.options.notFoundMode,
destRoutes,
)
}
}

// If there are any params, we need to stringify them
if (Object.keys(nextParams).length > 0) {
Expand Down Expand Up @@ -1877,7 +1878,7 @@ export class RouterCore<
routes: destRoutes,
params: snapshotParams,
searchStr,
globalNotFoundRouteId: globalNotFoundMatch?.routeId,
globalNotFoundRouteId,
})

// Create the full path of the location
Expand Down Expand Up @@ -3151,3 +3152,18 @@ function applySearchMiddleware({
// Start applying middlewares
return applyNext(0, search)
}

function findGlobalNotFoundRouteId(
notFoundMode: 'root' | 'fuzzy' | undefined,
routes: ReadonlyArray<AnyRoute>,
) {
if (notFoundMode !== 'root') {
for (let i = routes.length - 1; i >= 0; i--) {
const route = routes[i]!
if (route.children) {
return route.id
}
}
}
return rootRouteId
}
8 changes: 4 additions & 4 deletions packages/solid-router/tests/useParams.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ test('useParams must return parsed result if applicable.', async () => {

expect(window.location.pathname).toBe('/posts/category_first')
expect(await screen.findByTestId('post-category-heading')).toBeInTheDocument()
expect(mockedfn).toHaveBeenCalledTimes(1)
expect(mockedfn).not.toHaveBeenCalled()

mockedfn.mockClear()
await waitFor(() => fireEvent.click(firstPostLink))
Expand All @@ -211,7 +211,7 @@ test('useParams must return parsed result if applicable.', async () => {
expect(renderedPost.category).toBe('one')
expect(paramCategoryValue.textContent).toBe('one')
expect(paramPostIdValue.textContent).toBe('1')
expect(mockedfn).toHaveBeenCalledTimes(2)
expect(mockedfn).toHaveBeenCalledTimes(1)
expect(allCategoryLink).toBeInTheDocument()

mockedfn.mockClear()
Expand All @@ -222,7 +222,7 @@ test('useParams must return parsed result if applicable.', async () => {
expect(window.location.pathname).toBe('/posts/category_all')
expect(await screen.findByTestId('post-category-heading')).toBeInTheDocument()
expect(secondPostLink).toBeInTheDocument()
expect(mockedfn).toHaveBeenCalledTimes(2)
expect(mockedfn).not.toHaveBeenCalled()

mockedfn.mockClear()
await waitFor(() => fireEvent.click(secondPostLink))
Expand All @@ -244,5 +244,5 @@ test('useParams must return parsed result if applicable.', async () => {
expect(renderedPost.category).toBe('two')
expect(paramCategoryValue.textContent).toBe('all')
expect(paramPostIdValue.textContent).toBe('2')
expect(mockedfn).toHaveBeenCalledTimes(2)
expect(mockedfn).toHaveBeenCalledTimes(1)
})
8 changes: 4 additions & 4 deletions packages/vue-router/tests/useParams.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ test('useParams must return parsed result if applicable.', async () => {

expect(window.location.pathname).toBe('/posts/category_first')
expect(await screen.findByTestId('post-category-heading')).toBeInTheDocument()
expect(mockedfn).toHaveBeenCalledTimes(1)
expect(mockedfn).not.toHaveBeenCalled()

mockedfn.mockClear()
await waitFor(() => fireEvent.click(firstPostLink))
Expand All @@ -216,7 +216,7 @@ test('useParams must return parsed result if applicable.', async () => {
expect(renderedPost.category).toBe('one')
expect(paramCategoryValue.textContent).toBe('one')
expect(paramPostIdValue.textContent).toBe('1')
expect(mockedfn).toHaveBeenCalledTimes(2)
expect(mockedfn).toHaveBeenCalledTimes(1)
expect(allCategoryLink).toBeInTheDocument()

mockedfn.mockClear()
Expand All @@ -227,7 +227,7 @@ test('useParams must return parsed result if applicable.', async () => {
expect(window.location.pathname).toBe('/posts/category_all')
expect(await screen.findByTestId('post-category-heading')).toBeInTheDocument()
expect(secondPostLink).toBeInTheDocument()
expect(mockedfn).toHaveBeenCalledTimes(2)
expect(mockedfn).not.toHaveBeenCalled()

mockedfn.mockClear()
await waitFor(() => fireEvent.click(secondPostLink))
Expand All @@ -249,5 +249,5 @@ test('useParams must return parsed result if applicable.', async () => {
expect(renderedPost.category).toBe('two')
expect(paramCategoryValue.textContent).toBe('all')
expect(paramPostIdValue.textContent).toBe('2')
expect(mockedfn).toHaveBeenCalledTimes(2)
expect(mockedfn).toHaveBeenCalledTimes(1)
})
Loading