Skip to content

Commit

Permalink
fix(react-router): reset error boundary after the new matches are rea…
Browse files Browse the repository at this point in the history
…dy (#2244)

* fix(react-router)(issue-2162): reset error boundary after the new matches are ready

* tests: reproducer for #2043

---------

Co-authored-by: Cristian Langa <cristian.langa@flywire.com>
Co-authored-by: Manuel Schiller <manuel.schiller@caligano.de>
  • Loading branch information
3 people committed Sep 2, 2024
1 parent bbc5148 commit 17d9885
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 5 deletions.
6 changes: 1 addition & 5 deletions packages/react-router/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1643,11 +1643,6 @@ export class Router<
load = async (): Promise<void> => {
this.latestLocation = this.parseLocation(this.latestLocation)

this.__store.setState((s) => ({
...s,
loadedAt: Date.now(),
}))

let redirect: ResolvedRedirect | undefined
let notFound: NotFoundError | undefined

Expand Down Expand Up @@ -1738,6 +1733,7 @@ export class Router<
return {
...s,
isLoading: false,
loadedAt: Date.now(),
matches: newMatches,
pendingMatches: undefined,
cachedMatches: [
Expand Down
71 changes: 71 additions & 0 deletions packages/react-router/tests/link.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,77 @@ describe('Link', () => {
expect(onError).toHaveBeenCalledOnce()
})

test('when navigating away from a route with a loader that errors', async () => {
const postsOnError = vi.fn()
const indexOnError = vi.fn()
const rootRoute = createRootRoute({
component: () => (
<>
<div>
<Link to="/">Index</Link> <Link to="/posts">Posts</Link>
</div>
<hr />
<Outlet />
</>
),
})
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
component: () => {
return (
<>
<h1>Index</h1>
</>
)
},
onError: indexOnError,
errorComponent: () => <span>IndexError</span>,
})

const error = new Error('Something went wrong!')

const postsRoute = createRoute({
getParentRoute: () => rootRoute,
path: 'posts',
loaderDeps: (opts) => ({ page: opts.search }),
loader: () => {
throw error
},
onError: postsOnError,
errorComponent: () => <span>PostsError</span>,
component: () => {
return (
<>
<h1>Posts</h1>
</>
)
},
})

const router = createRouter({
routeTree: rootRoute.addChildren([indexRoute, postsRoute]),
})

render(<RouterProvider router={router} />)

const postsLink = await screen.findByRole('link', { name: 'Posts' })

fireEvent.click(postsLink)

const postsErrorText = await screen.findByText('PostsError')
expect(postsErrorText).toBeInTheDocument()

expect(postsOnError).toHaveBeenCalledOnce()
expect(postsOnError).toHaveBeenCalledWith(error)

const indexLink = await screen.findByRole('link', { name: 'Index' })
fireEvent.click(indexLink)

expect(screen.findByText('IndexError')).rejects.toThrow()
expect(indexOnError).not.toHaveBeenCalledOnce()
})

test('when navigating to /posts with a beforeLoad that redirects', async () => {
const rootRoute = createRootRoute()
const indexRoute = createRoute({
Expand Down

0 comments on commit 17d9885

Please sign in to comment.