Skip to content

Commit ddc2b94

Browse files
chore: Update version for release (pre) (#11089)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 1752d84 commit ddc2b94

File tree

11 files changed

+761
-11
lines changed

11 files changed

+761
-11
lines changed

.changeset/pre.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,11 @@
88
"react-router-native": "6.20.1",
99
"@remix-run/router": "1.13.1"
1010
},
11-
"changesets": []
11+
"changesets": [
12+
"catch-unwrap-error",
13+
"handle-falsy-errors",
14+
"partial-hydration-data",
15+
"pretty-dolphins-relax",
16+
"relative-splat-path"
17+
]
1218
}

packages/react-router-dom-v5-compat/CHANGELOG.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,146 @@
11
# `react-router-dom-v5-compat`
22

3+
## 6.21.0-pre.0
4+
5+
### Minor Changes
6+
7+
- Add a new `future.v7_relativeSplatPath` flag to implenent a breaking bug fix to relative routing when inside a splat route. ([#11087](https://github.com/remix-run/react-router/pull/11087))
8+
9+
This fix was originally added in [#10983](https://github.com/remix-run/react-router/issues/10983) and was later reverted in [#11078](https://github.com/remix-run/react-router/issues/110788) because it was determined that a large number of existing applications were relying on the buggy behavior (see [#11052](https://github.com/remix-run/react-router/issues/11052))
10+
11+
**The Bug**
12+
The buggy behavior is that without this flag, the default behavior when resolving relative paths is to _ignore_ any splat (`*`) portion of the current route path.
13+
14+
**The Background**
15+
This decision was originally made thinking that it would make the concept of nested different sections of your apps in `<Routes>` easier if relative routing would _replace_ the current splat:
16+
17+
```jsx
18+
<BrowserRouter>
19+
<Routes>
20+
<Route path="/" element={<Home />} />
21+
<Route path="dashboard/*" element={<Dashboard />} />
22+
</Routes>
23+
</BrowserRouter>
24+
```
25+
26+
Any paths like `/dashboard`, `/dashboard/team`, `/dashboard/projects` will match the `Dashboard` route. The dashboard component itself can then render nested `<Routes>`:
27+
28+
```jsx
29+
function Dashboard() {
30+
return (
31+
<div>
32+
<h2>Dashboard</h2>
33+
<nav>
34+
<Link to="/">Dashboard Home</Link>
35+
<Link to="team">Team</Link>
36+
<Link to="projects">Projects</Link>
37+
</nav>
38+
39+
<Routes>
40+
<Route path="/" element={<DashboardHome />} />
41+
<Route path="team" element={<DashboardTeam />} />
42+
<Route path="projects" element={<DashboardProjects />} />
43+
</Routes>
44+
</div>
45+
);
46+
}
47+
```
48+
49+
Now, all links and route paths are relative to the router above them. This makes code splitting and compartmentalizing your app really easy. You could render the `Dashboard` as its own independent app, or embed it into your large app without making any changes to it.
50+
51+
**The Problem**
52+
53+
The problem is that this concept of ignoring part of a pth breaks a lot of other assumptions in React Router - namely that `"."` always means the current location pathname for that route. When we ignore the splat portion, we start getting invalid paths when using `"."`:
54+
55+
```jsx
56+
// If we are on URL /dashboard/team, and we want to link to /dashboard/team:
57+
function DashboardTeam() {
58+
// ❌ This is broken and results in <a href="/dashboard">
59+
return <Link to=".">A broken link to the Current URL</Link>;
60+
61+
// ✅ This is fixed but super unintuitive since we're already at /dashboard/team!
62+
return <Link to="./team">A broken link to the Current URL</Link>;
63+
}
64+
```
65+
66+
We've also introduced an issue that we can no longer move our `DashboardTeam` component around our route hierarchy easily - since it behaves differently if we're underneath a non-splat route, such as `/dashboard/:widget`. Now, our `"."` links will, properly point to ourself _inclusive of the dynamic param value_ so behavior will break from it's corresponding usage in a `/dashboard/*` route.
67+
68+
Even worse, consider a nested splat route configuration:
69+
70+
```jsx
71+
<BrowserRouter>
72+
<Routes>
73+
<Route path="dashboard">
74+
<Route path="*" element={<Dashboard />} />
75+
</Route>
76+
</Routes>
77+
</BrowserRouter>
78+
```
79+
80+
Now, a `<Link to=".">` and a `<Link to="..">` inside the `Dashboard` component go to the same place! That is definitely not correct!
81+
82+
Another common issue arose in Data Routers (and Remix) where any `<Form>` should post to it's own route `action` if you the user doesn't specify a form action:
83+
84+
```jsx
85+
let router = createBrowserRouter({
86+
path: "/dashboard",
87+
children: [
88+
{
89+
path: "*",
90+
action: dashboardAction,
91+
Component() {
92+
// ❌ This form is broken! It throws a 405 error when it submits because
93+
// it tries to submit to /dashboard (without the splat value) and the parent
94+
// `/dashboard` route doesn't have an action
95+
return <Form method="post">...</Form>;
96+
},
97+
},
98+
],
99+
});
100+
```
101+
102+
This is just a compounded issue from the above because the default location for a `Form` to submit to is itself (`"."`) - and if we ignore the splat portion, that now resolves to the parent route.
103+
104+
**The Solution**
105+
If you are leveraging this behavior, it's recommended to enable the future flag, move your splat to it's own route, and leverage `../` for any links to "sibling" pages:
106+
107+
```jsx
108+
<BrowserRouter>
109+
<Routes>
110+
<Route path="dashboard">
111+
<Route path="*" element={<Dashboard />} />
112+
</Route>
113+
</Routes>
114+
</BrowserRouter>
115+
116+
function Dashboard() {
117+
return (
118+
<div>
119+
<h2>Dashboard</h2>
120+
<nav>
121+
<Link to="..">Dashboard Home</Link>
122+
<Link to="../team">Team</Link>
123+
<Link to="../projects">Projects</Link>
124+
</nav>
125+
126+
<Routes>
127+
<Route path="/" element={<DashboardHome />} />
128+
<Route path="team" element={<DashboardTeam />} />
129+
<Route path="projects" element={<DashboardProjects />} />
130+
</Router>
131+
</div>
132+
);
133+
}
134+
```
135+
136+
This way, `.` means "the full current pathname for my route" in all cases (including static, dynamic, and splat routes) and `..` always means "my parents pathname".
137+
138+
### Patch Changes
139+
140+
- Updated dependencies:
141+
- `react-router@6.21.0-pre.0`
142+
- `react-router-dom@6.21.0-pre.0`
143+
3144
## 6.20.1
4145

5146
### Patch Changes

packages/react-router-dom-v5-compat/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-router-dom-v5-compat",
3-
"version": "6.20.1",
3+
"version": "6.21.0-pre.0",
44
"description": "Migration path to React Router v6 from v4/5",
55
"keywords": [
66
"react",
@@ -24,7 +24,7 @@
2424
"types": "./dist/index.d.ts",
2525
"dependencies": {
2626
"history": "^5.3.0",
27-
"react-router": "6.20.1"
27+
"react-router": "6.21.0-pre.0"
2828
},
2929
"peerDependencies": {
3030
"react": ">=16.8",

packages/react-router-dom/CHANGELOG.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,146 @@
11
# `react-router-dom`
22

3+
## 6.21.0-pre.0
4+
5+
### Minor Changes
6+
7+
- Add a new `future.v7_relativeSplatPath` flag to implenent a breaking bug fix to relative routing when inside a splat route. ([#11087](https://github.com/remix-run/react-router/pull/11087))
8+
9+
This fix was originally added in [#10983](https://github.com/remix-run/react-router/issues/10983) and was later reverted in [#11078](https://github.com/remix-run/react-router/issues/110788) because it was determined that a large number of existing applications were relying on the buggy behavior (see [#11052](https://github.com/remix-run/react-router/issues/11052))
10+
11+
**The Bug**
12+
The buggy behavior is that without this flag, the default behavior when resolving relative paths is to _ignore_ any splat (`*`) portion of the current route path.
13+
14+
**The Background**
15+
This decision was originally made thinking that it would make the concept of nested different sections of your apps in `<Routes>` easier if relative routing would _replace_ the current splat:
16+
17+
```jsx
18+
<BrowserRouter>
19+
<Routes>
20+
<Route path="/" element={<Home />} />
21+
<Route path="dashboard/*" element={<Dashboard />} />
22+
</Routes>
23+
</BrowserRouter>
24+
```
25+
26+
Any paths like `/dashboard`, `/dashboard/team`, `/dashboard/projects` will match the `Dashboard` route. The dashboard component itself can then render nested `<Routes>`:
27+
28+
```jsx
29+
function Dashboard() {
30+
return (
31+
<div>
32+
<h2>Dashboard</h2>
33+
<nav>
34+
<Link to="/">Dashboard Home</Link>
35+
<Link to="team">Team</Link>
36+
<Link to="projects">Projects</Link>
37+
</nav>
38+
39+
<Routes>
40+
<Route path="/" element={<DashboardHome />} />
41+
<Route path="team" element={<DashboardTeam />} />
42+
<Route path="projects" element={<DashboardProjects />} />
43+
</Routes>
44+
</div>
45+
);
46+
}
47+
```
48+
49+
Now, all links and route paths are relative to the router above them. This makes code splitting and compartmentalizing your app really easy. You could render the `Dashboard` as its own independent app, or embed it into your large app without making any changes to it.
50+
51+
**The Problem**
52+
53+
The problem is that this concept of ignoring part of a pth breaks a lot of other assumptions in React Router - namely that `"."` always means the current location pathname for that route. When we ignore the splat portion, we start getting invalid paths when using `"."`:
54+
55+
```jsx
56+
// If we are on URL /dashboard/team, and we want to link to /dashboard/team:
57+
function DashboardTeam() {
58+
// ❌ This is broken and results in <a href="/dashboard">
59+
return <Link to=".">A broken link to the Current URL</Link>;
60+
61+
// ✅ This is fixed but super unintuitive since we're already at /dashboard/team!
62+
return <Link to="./team">A broken link to the Current URL</Link>;
63+
}
64+
```
65+
66+
We've also introduced an issue that we can no longer move our `DashboardTeam` component around our route hierarchy easily - since it behaves differently if we're underneath a non-splat route, such as `/dashboard/:widget`. Now, our `"."` links will, properly point to ourself _inclusive of the dynamic param value_ so behavior will break from it's corresponding usage in a `/dashboard/*` route.
67+
68+
Even worse, consider a nested splat route configuration:
69+
70+
```jsx
71+
<BrowserRouter>
72+
<Routes>
73+
<Route path="dashboard">
74+
<Route path="*" element={<Dashboard />} />
75+
</Route>
76+
</Routes>
77+
</BrowserRouter>
78+
```
79+
80+
Now, a `<Link to=".">` and a `<Link to="..">` inside the `Dashboard` component go to the same place! That is definitely not correct!
81+
82+
Another common issue arose in Data Routers (and Remix) where any `<Form>` should post to it's own route `action` if you the user doesn't specify a form action:
83+
84+
```jsx
85+
let router = createBrowserRouter({
86+
path: "/dashboard",
87+
children: [
88+
{
89+
path: "*",
90+
action: dashboardAction,
91+
Component() {
92+
// ❌ This form is broken! It throws a 405 error when it submits because
93+
// it tries to submit to /dashboard (without the splat value) and the parent
94+
// `/dashboard` route doesn't have an action
95+
return <Form method="post">...</Form>;
96+
},
97+
},
98+
],
99+
});
100+
```
101+
102+
This is just a compounded issue from the above because the default location for a `Form` to submit to is itself (`"."`) - and if we ignore the splat portion, that now resolves to the parent route.
103+
104+
**The Solution**
105+
If you are leveraging this behavior, it's recommended to enable the future flag, move your splat to it's own route, and leverage `../` for any links to "sibling" pages:
106+
107+
```jsx
108+
<BrowserRouter>
109+
<Routes>
110+
<Route path="dashboard">
111+
<Route path="*" element={<Dashboard />} />
112+
</Route>
113+
</Routes>
114+
</BrowserRouter>
115+
116+
function Dashboard() {
117+
return (
118+
<div>
119+
<h2>Dashboard</h2>
120+
<nav>
121+
<Link to="..">Dashboard Home</Link>
122+
<Link to="../team">Team</Link>
123+
<Link to="../projects">Projects</Link>
124+
</nav>
125+
126+
<Routes>
127+
<Route path="/" element={<DashboardHome />} />
128+
<Route path="team" element={<DashboardTeam />} />
129+
<Route path="projects" element={<DashboardProjects />} />
130+
</Router>
131+
</div>
132+
);
133+
}
134+
```
135+
136+
This way, `.` means "the full current pathname for my route" in all cases (including static, dynamic, and splat routes) and `..` always means "my parents pathname".
137+
138+
### Patch Changes
139+
140+
- Updated dependencies:
141+
- `@remix-run/router@1.14.0-pre.0`
142+
- `react-router@6.21.0-pre.0`
143+
3144
## 6.20.1
4145

5146
### Patch Changes

packages/react-router-dom/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-router-dom",
3-
"version": "6.20.1",
3+
"version": "6.21.0-pre.0",
44
"description": "Declarative routing for React web applications",
55
"keywords": [
66
"react",
@@ -23,8 +23,8 @@
2323
"module": "./dist/index.js",
2424
"types": "./dist/index.d.ts",
2525
"dependencies": {
26-
"@remix-run/router": "1.13.1",
27-
"react-router": "6.20.1"
26+
"@remix-run/router": "1.14.0-pre.0",
27+
"react-router": "6.21.0-pre.0"
2828
},
2929
"devDependencies": {
3030
"react": "^18.2.0",

0 commit comments

Comments
 (0)