1. Redirect routes

React-router-dom 5.x implements the same usage as react-router-dom 5.x, including BrowserRouter, Link, Switch, Route, etc. The basic usage is shown in the following code:

<Router>
    <div>
        <Link to="/a">Component A</Link>
        <Link to="/b">The component B</Link>
        <Link to="/a/c">Component C</Link>
    </div>
    <Switch>
        <Route path="/a" component={A} />
        <Route path="/b" component={B} />
        <Route path="/a/c" component={C} />
    </Switch>
</Router>
Copy the code

2. BrowserRouter

The BrowserRouter component needs to wrap all the components together, using the Context to provide the history object and location object. Where the history object is provided by createBrowserHistory() and the location object has an initial value of window.location.

History.listen () is used to listen for location changes and update the location in state when it changes.

import { createContext, useState, useEffect } from 'react';
import { createBrowserHistory } from 'history';

const history = createBrowserHistory();
export const RouterContext = createContext();

const BrowserRouter = ({ children }) = > {
    const [location, setLocation] = useState(window.location);
    useEffect(() = > {
        // Listen for route changes
        const unlisten = history.listen(({ location: loc }) = > {
            setLocation(loc);
        });
        return () = >{ unlisten && unlisten(); }; } []);return (
        <RouterContext.Provider value={{ history.location}} >{children}</RouterContext.Provider>
    );
};

export default BrowserRouter;
Copy the code

3. Link

The Link component is actually a Link. However, when a route is clicked, it does not actually jump, so the default behavior of a link jump is blocked in the onClick event. It also uses history.push() to push the current location onto the history stack, triggering listeners in BrowserRouter to update the location in state. The window.location will also be updated and the URL will change.

import { useContext } from 'react';
import { RouterContext } from './BrowserRouter';

const style = {
    border: '2px solid blue'.padding: '10px'.margin: '20px'.textDecoration: 'none'};const Link = ({ to, children }) = > {
    const { history } = useContext(RouterContext);
    return (
        <a
            href={to}
            style={style}
            onClick={e= > {
                e.preventDefault();
                history.push(to);
            }}
        >
            {children}
        </a>
    );
};

export default Link;
Copy the code

4. Switch

The Switch component wraps a series of Route components. If there are multiple Route components, children is an array; If there is only one Route, children is a single element, so make sure to convert to an array.

Compare the location.pathname in the state to the path component containing the Route component, rendering only matching routes.

import { useContext } from 'react';
import { RouterContext } from './BrowserRouter';

const Switch = ({ children }) = > {
    const { location } = useContext(RouterContext);
    const routes = Array.isArray(children) ? children : [children];
    return (
        <>
            {routes.map(child => {
                const {
                    props: { path },
                } = child;
                if (location.pathname === path) return child;
                return null;
            })}
        </>
    );
};

export default Switch;
Copy the code

5. Route

Compare the location. pathName in state with the path of the current Route, and if it matches, render the component passed in.

import { createElement, useContext } from 'react';
import { RouterContext } from './BrowserRouter';

const Route = ({ path, component }) = > {
    const { location } = useContext(RouterContext);
    return <>{location.pathname === path ? createElement(component) : null}</>;
};

export default Route;
Copy the code

6. The source code

“Lot”


The above is my humble opinion of learning, if there is anything wrong, welcome to point out the exchange!