Skip to content

Commit fb04daf

Browse files
fix(react-router, solid-router): reduce useNavigate reactivity on path changes (#5037)
This is a follow-up to #4978. As picked up by @Sheraff the changes made caused useNavigate to negatively impact performance specifically with useNavigate being too reactive to path changes. This reverts the use of useActiveLocation, that acted as a single implementation of the logic to determine the from location, and moves the determination of the from path back to each of Link and useNavigate. While the core logic is still the same across the implementations the implication of how it's used and the sources of the required inputs are different enough that it warrants separate implementations. This PR does not revert the full change set and still applies to core reasons and changes for the previous commit in keeping the logic for determining the from clause the same, i.e. the order of determining the from path for navigation remains: from clause => current location => rendered location. @Sheraff to advise if this implementation resolves the issues he picked up. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * Breaking Changes * Removed active-location hooks and their associated types from React and Solid packages. * Refactor * Link and navigation now accept an explicit "from" option instead of deriving it from active-location state. * New Features * Added a programmatic Navigate helper for Solid to trigger navigation on mount. * Bug Fixes * More predictable fallback behavior when no explicit "from" is provided. * Performance * Reduced state subscriptions for minor efficiency gains. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent d872397 commit fb04daf

File tree

46 files changed

+2426
-152
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2426
-152
lines changed

e2e/react-router/basic-file-based/src/routeTree.gen.ts

Lines changed: 396 additions & 0 deletions
Large diffs are not rendered by default.

e2e/react-router/basic-file-based/src/routes/__root.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ function RootComponent() {
122122
>
123123
redirect
124124
</Link>{' '}
125+
<Link
126+
to="/relative"
127+
activeProps={{
128+
className: 'font-bold',
129+
}}
130+
>
131+
relative routing
132+
</Link>{' '}
125133
<Link
126134
// @ts-expect-error
127135
to="/this-route-does-not-exist"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Link, Outlet, createFileRoute } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/relative/')({
4+
component: RouteComponent,
5+
})
6+
7+
function RouteComponent() {
8+
return (
9+
<div className="p-2">
10+
<div className="border-b" data-testid="relative-routing-home">
11+
Relative Routing Tests - Home
12+
</div>
13+
<div>
14+
<Link to="/relative/link">Using Links</Link>
15+
<Link to="/relative/useNavigate">Using useNavigate</Link>
16+
</div>
17+
<div>
18+
<Outlet />
19+
</div>
20+
</div>
21+
)
22+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { createFileRoute } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/relative/link/nested/deep/')({
4+
component: RouteComponent,
5+
})
6+
7+
function RouteComponent() {
8+
return (
9+
<div data-testid="relative-link-nested-deep-header">
10+
Hello "/relative/link/nested/deep/"!
11+
</div>
12+
)
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { createFileRoute } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/relative/link/nested/')({
4+
component: RouteComponent,
5+
})
6+
7+
function RouteComponent() {
8+
return (
9+
<div data-testid="relative-link-nested-header">
10+
Hello "/relative/link/nested/"!
11+
</div>
12+
)
13+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Link, createFileRoute } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/relative/link/path/$path/')({
4+
component: RouteComponent,
5+
loader: ({ params }) => {
6+
return params
7+
},
8+
})
9+
10+
function RouteComponent() {
11+
const { path } = Route.useParams()
12+
13+
return (
14+
<div className="p-2">
15+
<div className="border-b" data-testid="relative-link-path-param-header">
16+
Hello from "/relative/links/path/{path}"!
17+
</div>
18+
<div>
19+
<Link
20+
from="/relative/link/path"
21+
to="./$path"
22+
params={{ path: path === 'a' ? 'b' : 'a' }}
23+
className="mr-2"
24+
data-testid="relative-link-path-param-switchAB"
25+
>
26+
To {path === 'a' ? 'b' : 'a'}
27+
</Link>
28+
</div>
29+
</div>
30+
)
31+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Outlet, createFileRoute } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/relative/link/path/')({
4+
component: RouteComponent,
5+
})
6+
7+
function RouteComponent() {
8+
return (
9+
<div className="p-2">
10+
<div className="border-b" data-testid="relative-link-path-header">
11+
Relative Routing Tests - Path Params
12+
</div>
13+
<div>
14+
<Outlet />
15+
</div>
16+
</div>
17+
)
18+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { createFileRoute } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/relative/link/relative-link-a')({
4+
component: RouteComponent,
5+
})
6+
7+
function RouteComponent() {
8+
return (
9+
<div data-testid="relative-link-a-header">
10+
Hello "/relative/link/relative-link-a"!
11+
</div>
12+
)
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { createFileRoute } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/relative/link/relative-link-b')({
4+
component: RouteComponent,
5+
})
6+
7+
function RouteComponent() {
8+
return (
9+
<div data-testid="relative-link-b-header">
10+
Hello "/relative/link/relative-link-b"!
11+
</div>
12+
)
13+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import {
2+
Link,
3+
Outlet,
4+
createFileRoute,
5+
useNavigate,
6+
} from '@tanstack/react-router'
7+
import { useEffect } from 'react'
8+
9+
export const Route = createFileRoute('/relative/link')({
10+
component: RouteComponent,
11+
})
12+
13+
function RouteComponent() {
14+
const navigate = useNavigate()
15+
16+
useEffect(() => {
17+
console.log('navigate')
18+
}, [navigate])
19+
20+
return (
21+
<div className="p-2">
22+
<div className="border-b" data-testid="relative-link-header">
23+
Relative Routing - Links - Index
24+
</div>
25+
<div>
26+
<Link
27+
from="/relative/link"
28+
to=".."
29+
data-testid="relative-link-home"
30+
className="mr-2 underline"
31+
>
32+
Return To Home
33+
</Link>
34+
<Link
35+
from="/relative/link"
36+
to="."
37+
data-testid="relative-link-index"
38+
className="mr-2"
39+
>
40+
Return To Index
41+
</Link>
42+
<Link
43+
to="."
44+
data-testid="relative-link-reload"
45+
className="mr-2 underline"
46+
>
47+
Reload
48+
</Link>
49+
<Link
50+
to=".."
51+
data-testid="relative-link-back"
52+
className="mr-2 underline"
53+
>
54+
Back
55+
</Link>
56+
<Link
57+
from="/relative/link"
58+
to="./relative-link-a"
59+
data-testid="relative-link-a"
60+
className="mr-2 underline"
61+
>
62+
To Relative Link A
63+
</Link>
64+
<Link
65+
from="/relative/link"
66+
to="./relative-link-b"
67+
data-testid="relative-link-b"
68+
className="mr-2 underline"
69+
>
70+
To Relative Link B
71+
</Link>
72+
<Link
73+
from="/relative/link"
74+
to="./nested/deep"
75+
data-testid="relative-link-deeply-nested"
76+
className="mr-2 underline"
77+
>
78+
To Deeply Nested
79+
</Link>
80+
<Link
81+
to="/relative/link/path/$path"
82+
params={{ path: 'a' }}
83+
data-testid="relative-link-path"
84+
className="mr-2 underline"
85+
>
86+
To Path Param A
87+
</Link>
88+
<Link
89+
from="/relative/link"
90+
to="./with-search"
91+
search={{ searchParam: '1' }}
92+
data-testid="relative-link-withSearch"
93+
className="mr-2 underline"
94+
>
95+
To With Search Params
96+
</Link>
97+
</div>
98+
<div>
99+
<Outlet />
100+
</div>
101+
</div>
102+
)
103+
}

0 commit comments

Comments
 (0)