foreword
React Router
to v6.2.2
Why launch v6
- The biggest reason for the introduction of
v6
is the appearance ofReact Hooks
v6
writes more compact and elegant code thanv5
Let's feel it through the code, this is the pseudo code written by v6
import { Routes, Route, useParams } from "react-router-dom";
function App() {
return (
<Routes>
<Route path="blog/:id" element={<Head />} />
</Routes>
);
}
function Head() {
let { id } = useParams();
return (
<>
<Footer />
</>
);
}
function Footer() {
let { id } = useParams();
}
This is pseudo code written by v5
import * as React from "react";
import { Switch, Route } from "react-router-dom";
class App extends React.Component {
render() {
return (
<Switch>
<Route
path="head/:id"
render={({ match }) => (
<Head id={match.params.id} />
)}
/>
</Switch>
);
}
}
class Head extends React.Component {
render() {
return (
<>
<Footer id={this.props.id} />
</>
);
}
}
class Footer extends React.Component {
render() {
return (
<>
<ButtonComponent id={this.props.id} />
</>
);
}
}
This example shows
Hooks
removes the need to use<Route render>
to access the internal state of the router- Manually pass
props
the need to propagate that state to child components - App package size is smaller
What features have been added?
<Switch>
upgraded to<Routes>
- All <Route> and <Link> within Routes are relative. This makes the code in <Route path> and <Link to> leaner and more predictable
- Routing is based on the best match, rather than traversing in order, which avoids errors due to unreachable routes
- Routes can be nested in one place instead of being scattered across different components
- New hook
useRoutes
instead ofreact-router-config
Before:
import React, { lazy } from 'react';
import PrivateRoute from '@components/PrivateRoute/index';
const Dashboard = lazy(() => import('@pages/dashboard/index'));
const Abount = lazy(() => import('@pages/abount/index'));
const routes = [
{
path: '/home',
component: Dashboard
},
{
path: '/about',
component: Abount
},
];
const RouteWithSubRoutes = route => (
<PrivateRoute path={route.path} component={route.component} routes={route.routes} />
);
const routeConfig = routes.map((route, i) => <RouteWithSubRoutes key={i} {...route} />);
export default routeConfig;
Now
function App() {
let element = useRoutes([
{ path: '/', element: <Home /> },
{
path: 'users',
element: <Users />,
children: [
{ path: '/', element: <UsersIndex /> },
{ path: ':id', element: <UserProfile /> },
{ path: 'me', element: <OwnUserProfile /> },
]
}
]);
return element;
}
feel more elegant
- Replace
useNavigate
withuseHistory
Before
import { useHistory } from "react-router-dom";
function App() {
let history = useHistory();
function handleClick() {
history.push("/home");
}
return (
<div>
<button onClick={handleClick}>go home</button>
</div>
);
}
Now
import { useNavigate } from "react-router-dom";
function App() {
let navigate = useNavigate();
function handleClick() {
navigate("/home");
}
return (
<div>
<button onClick={handleClick}>go home</button>
</div>
);
}
It's not a big change
- Route changes
- 4.1
<Route exact>
removed, use/*
instead
<Route path="/*" element={<Home />} />
`
- 4.2
<Route children>
use<Route element>
instead
import Profile from './Profile';
// v5
<Route path=":userId" component={<Profile />} />
// v6
<Route path=":userId" element={<Profile />} />
- 4.3 Outlet
We use a<Outlet>
element as a placeholder. In the case of<Outlet>
, how does theUsers
component render its child routes. So a<UserProfile>
or<OwnUserProfile>
element will be rendered depending on the current position<Outlet>
- 4.4
import {
BrowserRouter,
Routes,
Route,
Link,
Outlet
} from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="users" element={<Users />}>
<Route path="/" element={<UsersIndex />} />
<Route path=":id" element={<UserProfile />} />
<Route path="me" element={<OwnUserProfile />} />
</Route>
</Routes>
</BrowserRouter>
);
}
function Users() {
return (
<div>
<nav>
<Link to="me">My Profile</Link>
</nav>
<Outlet />
</div>
);
}
experience v6
Here we use create-react-app
to create the project, after installation, enter the project and install react-router-dom@6
dependencies
$ npx create-react-app react-app
$ cd react-app
$ npm install react-router-dom@6
src/index.js
in editor, 062409f2d23441 imports BrowserRouter
from near the react-router-dom
and <APP>
in <BrowserRouter>
// src/index.js
import * as React from "react";
import * as ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById("root")
);
Open src/App.js
and replace the default markers with some routes
// App.js
import * as React from "react";
import { Routes, Route, Link } from "react-router-dom";
import "./App.css";
function App() {
return (
<div className="App">
<h1>Welcome to React Router!</h1>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Routes>
</div>
);
}
Now, still at src/App.js
, create your routing component
// src/App.js
function Home() {
return (
<>
<main>
<h2>Home</h2>
</main>
<nav>
<Link to="/about">About</Link>
</nav>
</>
);
}
function About() {
return (
<>
<main>
<h2>About</h2>
</main>
<nav>
<Link to="/">Home</Link>
</nav>
</>
);
}
Run npm start
and you should see the Home
logo
How to upgrade v6
The official migration guide is here: React Router v6 migration guide
Reference article
Epilogue
If you are refactoring your app with Hook
, my suggestion is to try
Important matter
If you think this content is very inspiring to you, don't forget to like + follow
Welcome to add my personal WeChat: Jiang9684, to exchange front-end technology together
My blog address
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。