Skip to content

Commit 10a6fd0

Browse files
authored
more v7 docs (#11602)
* docs: finish v6 upgrade guide * add vite adoption stub
1 parent 0374749 commit 10a6fd0

File tree

2 files changed

+283
-78
lines changed

2 files changed

+283
-78
lines changed

docs/upgrading/v6.md

Lines changed: 175 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -6,128 +6,225 @@ new: true
66

77
# Upgrading from v6
88

9-
## Future Flags
9+
The v7 upgrade is non-breaking if you are caught up on all future flags. These flags allow you to update your app one change at a time. We highly recommend you make a commit after each step and ship it instead of doing everything all at once.
1010

11-
If you are current on all future flags in v6, the v7 upgrade is non-breaking.
11+
## Update to latest v6.x
1212

13-
First update to the latest minor version of v6.x and then the console will warn you for any flags that you have not enabled.
13+
First update to the latest minor version of v6.x to have the latest future flags and console warnings.
1414

15-
```tsx
16-
export interface FutureConfig {
17-
v7_fetcherPersist: boolean;
18-
v7_normalizeFormMethod: boolean;
19-
v7_partialHydration: boolean;
20-
v7_prependBasename: boolean;
21-
v7_relativeSplatPath: boolean;
22-
v7_startTransition: boolean;
23-
}
15+
👉 **Update to latest v6**
16+
17+
```shellscript nonumber
18+
npm install react-router-dom@6
2419
```
2520

26-
Once you are caught up, you can simply update to the latest version of v7 (theoretically!) without issue.
21+
### v7_relativeSplatPath
2722

28-
```shellscript nonumber
29-
npm install react-router-dom@7
23+
**Background**
24+
25+
Changes the relative path matching and linking for multi-segment splats paths like `dashboard/*` (vs. just `*`). [View the CHANGELOG](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md#minor-changes-2) for more information.
26+
27+
👉 **Enable the flag**
28+
29+
Enabling the flag depends on the type of router:
30+
31+
```tsx
32+
<BrowserRouter
33+
future={{
34+
v7_relativeSplatPath: true,
35+
}}
36+
/>
3037
```
3138

32-
## Bundler Plugins
39+
```tsx
40+
createBrowserRouter(routes, {
41+
future: {
42+
v7_relativeSplatPath: true,
43+
},
44+
});
45+
```
3346

34-
The rest of this document is optional. It describes how to incrementally take advantage of the new features in v7 including
47+
**Update your Code**
48+
49+
If you have any routes with a path + a splat like `<Route path="dashboard/*">` and has relative links like `<Link to="relative">` or `<Link to="../relative">` beneath it, you will need to update your code.
50+
51+
👉 **Split the `<Route>` into two**
52+
53+
Split any multi-segment splat `<Route>` into a parent route with the path and a child route with the splat:
54+
55+
```diff
56+
<Routes>
57+
<Route path="/" element={<Home />} />
58+
- <Route path="dashboard/*" element={<Dashboard />} />
59+
+ <Route path="dashboard">
60+
+ <Route path="*" element={<Dashboard />} />
61+
+ </Route>
62+
</Routes>
63+
64+
// or
65+
createBrowserRouter([
66+
{ path: "/", element: <Home /> },
67+
{
68+
- path: "dashboard/*",
69+
- element: <Dashboard />,
70+
+ path: "dashboard",
71+
+ children: [{ path: "*", element: <Dashboard /> }],
72+
},
73+
]);
74+
```
3575

36-
- route modules
37-
- automatic code-splitting
38-
- static pre-rendering
39-
- server rendering
40-
- React Server Components
76+
👉 **Update relative links**
77+
78+
Update any `<Link>` elements within that route tree to include the extra `..` relative segment to continue linking to the same place:
79+
80+
```diff
81+
function Dashboard() {
82+
return (
83+
<div>
84+
<h2>Dashboard</h2>
85+
<nav>
86+
- <Link to="/">Dashboard Home</Link>
87+
- <Link to="team">Team</Link>
88+
- <Link to="projects">Projects</Link>
89+
+ <Link to="../">Dashboard Home</Link>
90+
+ <Link to="../team">Team</Link>
91+
+ <Link to="../projects">Projects</Link>
92+
</nav>
93+
94+
<Routes>
95+
<Route path="/" element={<DashboardHome />} />
96+
<Route path="team" element={<DashboardTeam />} />
97+
<Route
98+
path="projects"
99+
element={<DashboardProjects />}
100+
/>
101+
</Routes>
102+
</div>
103+
);
104+
}
105+
```
41106

42-
We encourage you to take these steps to set your app up for future React features with React Server Components and Server Actions.
107+
### v7_startTransition
43108

44-
### Vite
109+
**Background**
45110

46-
First install the React Router vite plugin:
111+
This uses `React.useTransition` instead of `React.useState` for Router state updates. View the [CHANGELOG](https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v7_starttransition) for more information.
47112

48-
```shellscript nonumber
49-
npm install -D @react-router/vite
113+
👉 **Enable the flag**
114+
115+
```tsx
116+
<BrowserRouter
117+
future={{
118+
v7_startTransition: true,
119+
}}
120+
/>
121+
122+
// or
123+
<RouterProvider
124+
future={{
125+
v7_startTransition: true,
126+
}}
127+
/>
50128
```
51129

52-
Then swap out the React plugin for React Router. The `react` key accepts the same options as the React plugin.
130+
👉 **Update your Code**
131+
132+
You don't need to update anything unless you are using `React.lazy` _inside_ of a component.
133+
134+
Using `React.lazy` inside of a component is incompatible with `React.useTransition` (or other code that makes promises inside of components). Move `React.lazy` to the module scope and stop making promises inside of components. This is not a limitation of React Router but rather incorrect usage of React.
53135

54-
```diff filename=vite.config.ts
55-
-import react from '@vitejs/plugin-react'
56-
+import { plugin as app } from "@react-router/vite";
57-
import { defineConfig } from "vite";
136+
### v7_fetcherPersist
58137

138+
<docs-warning>If you are not using a `createBrowserRouter` you can skip this</docs-warning>
59139

60-
export default defineConfig({
61-
plugins: [
62-
- react(reactOptions)
63-
+ app({ react: reactOptions })
64-
],
140+
**Background**
141+
142+
The fetcher lifecycle is now based on when it returns to an idle state rather than when its owner component unmounts: [View the CHANGELOG](https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#persistence-future-flag-futurev7_fetcherpersist) for more information.
143+
144+
**Enable the Flag**
145+
146+
```tsx
147+
createBrowserRouter(routes, {
148+
future: {
149+
v7_fetcherPersist: true,
150+
},
65151
});
66152
```
67153

68-
### Webpack
154+
**Update your Code**
69155

70-
<docs-error>TODO: update this when we know exactly what it looks like</docs-error>
156+
It's unlikely to affect your app. You may want to check any usage of `useFetchers` as they may persist longer than they did before. Depending on what you're doing, you may render something longer than before.
71157

72-
If you are using Webpack, you will need to update your Webpack config to use the React Router plugin.
158+
### v7_normalizeFormMethod
73159

74-
```shellscript nonumber
75-
npm install -D @react-router/webpack
76-
```
160+
<docs-warning>If you are not using a `createBrowserRouter` you can skip this</docs-warning>
77161

78-
```ts filename=webpack.config.js
79-
import { ReactRouterPlugin } from "@react-router/webpack";
80-
export default {
81-
plugins: [new ReactRouterPlugin()],
82-
};
83-
```
162+
This normalizes `formMethod` fields as uppercase HTTP methods to align with the `fetch()` behavior. [View the CHANGELOG](https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#futurev7_normalizeformmethod) for more information.
84163

85-
### Create React App
164+
👉 **Enable the Flag**
86165

87-
<docs-error>TODO: update this when we know exactly what it looks like</docs-error>
166+
```tsx
167+
createBrowserRouter(routes, {
168+
future: {
169+
v7_normalizeFormMethod: true,
170+
},
171+
});
172+
```
88173

89-
- Eject and add the Webpack plugin
90-
- Switch to Vite: https://www.robinwieruch.de/vite-create-react-app/
174+
**Update your Code**
91175

92-
## Entry Points
176+
If any of your code is checking for lowercase HTTP methods, you will need to update it to check for uppercase HTTP methods (or call `toLowerCase()` on it).
93177

94-
After configuring the bundler, you'll need to shuffle around your app's entry points.
178+
👉 **Compare `formMethod` to UPPERCASE**
95179

96-
<docs-error>TODO: add more details here</docs-error>
180+
```diff
181+
-useNavigation().formMethod === "post"
182+
-useFetcher().formMethod === "get";
183+
+useNavigation().formMethod === "POST"
184+
+useFetcher().formMethod === "GET";
185+
```
97186

98-
- Move `index.html` template to `root.tsx`
99-
- Move entry/root component to `root.tsx` and `entry.client.tsx`
187+
### v7_partialHydration
100188

101-
## Enable SSR and Pre-rendering
189+
<docs-warning>If you are not using a `createBrowserRouter` you can skip this</docs-warning>
102190

103-
If you want to enable server rendering and static pre-rendering, you can do so with the `ssr` and `prerender` options in the bundler plugin.
191+
This allows SSR frameworks to provide only partial hydration data. It's unlikely you need to worry about this, just turn the flag on. [View the CHANGELOG](https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#partial-hydration) for more information.
104192

105-
```ts filename=vite.config.ts
106-
import { plugin as app } from "@react-router/vite";
107-
import { defineConfig } from "vite";
193+
👉 **Enable the Flag**
108194

109-
export default defineConfig({
110-
plugins: [
111-
app({
112-
ssr: true,
113-
async prerender() {
114-
return ["/", "/about", "/contact"];
115-
},
116-
}),
117-
],
195+
```tsx
196+
createBrowserRouter(routes, {
197+
future: {
198+
v7_partialHydration: true,
199+
},
118200
});
119201
```
120202

121-
See [Deploying][deploying] for more information on deploying a server.
203+
## Upgrade to v7
204+
205+
Now that your app is caught up, you can simply update to v7 (theoretically!) without issue.
122206

123-
## Route Modules
207+
👉 **install v7**
124208

125-
You can incrementally migrate your routes to route modules.
209+
```shellscript nonumber
210+
npm install react-router-dom@7
211+
```
126212

127-
First create a `routes.ts` file that exports your routes.
213+
Your app should continue to work but you'll get console warnings for importing from "react-router-dom". In v7 you can import everything directly from `"react-router"`.
128214

129-
```tsx filename=app/routes.ts
215+
👉 **Uninstall react-router-dom, install react-router**
130216

217+
```shellscript nonumber
218+
npm uninstall react-router-dom
219+
npm install react-router
220+
```
221+
222+
👉 **Update imports**
223+
224+
Instead of manually updating imports, you can use this command. Make sure your git working tree is clean though so you can revert if it doesn't work as expected.
225+
226+
```shellscript nonumber
227+
find ./path/to/src \( -name "*.tsx" -o -name "*.ts" -o -name "*.js" -o -name "*.jsx" \) -type f -exec sed -i '' 's|from "react-router-dom"|from "react-router"|g' {} +
131228
```
132229

133-
[deploying]: ../start/deploying
230+
Congratulations, you're now on v7!

0 commit comments

Comments
 (0)