10
头图

foreword

React Router to v6.2.2

Why launch v6

  • The biggest reason for the introduction of v6 is the appearance of React Hooks
  • v6 writes more compact and elegant code than v5

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?

  1. <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
  2. New hook useRoutes instead of react-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

  1. Replace useNavigate with useHistory

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

  1. 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 the Users 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


野生程序猿江辰
902 声望2.4k 粉丝

前网易高级前端开发工程师 | 矩阵创始人 | 独立开发者