React router V6 exploration

Time:2022-5-25

preface

It’s okay. Turn it overReact RouterThe document was found to have been pushed tov6.2.2Version, this version has made great changes. Let’s have a look

Why V6

  • introductionv6The biggest reason isReact HooksAppearance of
  • v6Write more code thanv5More compact and elegant code

Let’s feel it through the code. This isv6Pseudocode written

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 isv5Pseudocode written

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

  • HooksEliminates the use of<Route render>The need to access the internal state of the router
  • Manual transferpropsThe need to propagate this state to child components
  • Smaller application packages

React router V6 exploration

What features have been added?

  1. <Switch>Upgrade to<Routes>

    • All < route > and < link > within routes are relative. This makes the code in < route path > and < link to > simpler and more predictable
    • Routing is based on the best match rather than traversal in order, which avoids the error caused by unreachable routing
    • Routes can be nested in one place rather than scattered in different components
  2. New hookuseRoutesreplacereact-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;
}

It feels more elegant

  1. useuseNavigatereplaceuseHistory

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>
    );
}

This change is not great

  1. Change of route
  • 4.1 <Route exact>Remove, use/*replace
<Route path="/*" element={<Home />} />

`

  • 4.2 <Route children>use<Route element>replace
import Profile from './Profile';

// v5
<Route path=":userId" component={<Profile />} />

// v6
<Route path=":userId" element={<Profile />} />
  • 4.3 Outlet
    We use one<Outlet>Element as a placeholder. stay<Outlet>In this case,UsersHow the component renders its child routes. Therefore, it will be based on the current location<Outlet>Present a<UserProfile>or<OwnUserProfile>element
  • 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 usecreate-react-appTo create a project. After installation, enter the project and install[email protected]rely on

$ npx create-react-app react-app
$ cd react-app
$ npm install [email protected]

src/index.jsOpen in the editor,BrowserRouterImport from near the topreact-router-domAnd will<APP>Package 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")
);

opensrc/App.jsAnd replace the default tag 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, stillsrc/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>
        </>
    );
}

functionnpm start, you should seeHomeidentification

How to upgrade V6

The official migration guide is here: react router V6 migration guide

Reference articles

  • React Router v6 Preview
  • React Router

epilogue

If you’re usingHookRefactoring your application, my suggestion is to try

Important things

If you think this content is very enlightening to you, don’t forget to like + pay attention

Welcome to add my personal wechat: jiang9684. Let’s exchange front-end technology together

My blog address