Try not to use the React Router

import React from 'react';
import ReactDOM from 'react-dom';

const About = () = > {
  return <div>About</div>;
};
const Inbox = () = > {
  return <div>Inbox</div>;
};
const Home = () = > {
  return <div>Home</div>;
};

const App = () = > {
  const [hash, setHash] = React.useState(' ');

  const updateMenu = () = > {
    const hashValue = window.location.hash.replace(The '#'.' ') | |'home';
    setHash(hashValue);
  };

  React.useEffect(() = > {
    updateMenu();
    window.addEventListener('hashchange', updateMenu);
    return () = > {
      window.removeEventListener('hashchange', updateMenu); }; } []);const renderChild = () = > {
    let Child;
    switch (hash) {
      case '/about':
        Child = About;
        break;
      case '/inbox':
        Child = Inbox;
        break;
      default:
        Child = Home;
    }
    return <Child />;
  };

  return (
    <div>
      <h1>App</h1>
      <ul>
        <li>
          <a href="#/about">About</a>
        </li>
        <li>
          <a href="#/inbox">Inbox</a>
        </li>
      </ul>
      {renderChild()}
    </div>
  );
};

ReactDOM.render(<App />.document.body);
Copy the code

When the hash part of the URL changes,

renders a different

based on the hash. It seems straightforward, but it can get complicated quickly as the business evolves. To make our URL parsing smarter, we need to write a lot of code that specifies which nested UI component branches the URL should render.

Using the Router

import React from 'react';
import ReactDOM from 'react-dom';
import { Route, BrowserRouter, Link, Switch } from 'react-router-dom';

const About = () = > {
  return <div>About</div>;
};
const Inbox = () = > {
  return <div>Inbox</div>;
};
const home = () = > {
  return <div>home</div>;
};

const App = () = > {
  return (
    <div>
      <BrowserRouter>
        <h1>App</h1>
        <ul>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/inbox">Inbox</Link>
          </li>
        </ul>
        <Switch>
          <Route exact={true} path="/" component={home} />
          <Route exact={true} path="/about" component={About} />
          <Route exact={true} path="/inbox" component={Inbox} />
        </Switch>
      </BrowserRouter>
    </div>
  );
};

ReactDOM.render(<App />.document.body);
Copy the code

From the above configuration, the application knows how to render the following three urls

URL component
/ home
/about About
/inbox Inbox

The react – the router – dom example

URL Parameters

import React from 'react';
import ReactDOM from 'react-dom';
import { Route, BrowserRouter, Link, Switch, useParams } from 'react-router-dom';

const About = () = > {
  return <div>About</div>;
};
const Inbox = () = > {
  return <div>Inbox</div>;
};
const home = () = > {
  return <div>home</div>;
};
const Child = () = > {
  console.log('useParams:', useParams());
  const { id } = useParams() as any;
  return <div>ID: {ID}</div>;
};

const App = () = > {
  return (
    <div>
      <BrowserRouter basename="test">
        <h1>App</h1>
        <ul>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/inbox">Inbox</Link>
          </li>
          <li>
            <Link to="/child/yahoo">Yahoo</Link>
          </li>
          <li>
            <Link to="/child/modus-create">Modus Create</Link>
          </li>
        </ul>
        <Switch>
          <Route exact={true} path="/" component={home} />
          <Route exact={true} path="/about" component={About} />
          <Route exact={true} path="/inbox" component={Inbox} />
          <Route exact={true} path="/child/:id" children={<Child />} / ></Switch>
      </BrowserRouter>
    </div>
  );
};

ReactDOM.render(<App />.document.body);
Copy the code

UseParams returns the key/value pair object of the URL parameter. Use it to access mate.params currently

.

Tip: key (ID) of the key/value pair object, corresponding to the ID of path=”/child/:id”, for example: path=”/child/:slug”, {slug: XXX}

Nesting

import React from 'react';
import ReactDOM from 'react-dom';
import { Route, BrowserRouter, Link, Switch, useParams, useRouteMatch } from 'react-router-dom';

const Topics = () = > {
  console.log('useRouteMatch:', useRouteMatch());
  const { path, url } = useRouteMatch();

  return (
    <div>
      <h2>Topics</h2>
      <ul>
        <li>
          <Link to={` ${url} /rendering`} >Rendering with React</Link>
        </li>
        <li>
          <Link to={` ${url} /components`} >Components</Link>
        </li>
        <li>
          <Link to={` ${url} /props-v-state`} >Props v. State</Link>
        </li>
      </ul>

      <Switch>
        <Route exact path={path}>
          <h3>Please select a topic.</h3>
        </Route>
        <Route path={` ${path} /:topicId`} >
          <Topic />
        </Route>
      </Switch>
    </div>
  );
};

const Topic = () = > {
  const { topicId } = useParams() as any;

  return (
    <div>
      <h3>{topicId}</h3>
    </div>
  );
};
const home = () = > {
  return <div>home</div>;
};

const App = () = > {
  return (
    <div>
      <BrowserRouter basename="test">
        <h1>App</h1>
        <ul>
          <li>
            <Link to="/">home</Link>
          </li>
          <li>
            <Link to="/topics">topics</Link>
          </li>
        </ul>
        <Switch>
          <Route exact={true} path="/" component={home} />
          <Route path="/topics" component={Topics} />
        </Switch>
      </BrowserRouter>
    </div>
  );
};

ReactDOM.render(<App />.document.body);
Copy the code

UseRouteMatch attempts to match the current URL in the same way as

. It is primarily used to access matching data without actually rendering

Pay attention to the use of exact

Redirect (authentication)

import React, { useContext, createContext, useState } from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Switch, Route, Link, Redirect, useHistory, useLocation } from 'react-router-dom';

/* * Use createContext to pass data across components * first define a container and default values to pass in the parent, * then define shared data through a Provider, * then define shared data through a Consumer. Is a child component or grandson component to use), the specific implementation code is as follows: */
const authContext = createContext({});

const ProvideAuth = (props: any) = > {
  // Returns a permission management object
  const auth = useProvideAuth();
  return <authContext.Provider value={auth}>{props.children}</authContext.Provider>;
};

// Hooks were added after react16.8. You can use useContext in hooks to get consumers
const useAuth = () = > {
  return useContext(authContext);
};

// Used to manage permission to deliver data
const useProvideAuth = () = > {
  const [user, setUser] = useState(null as null | string);

  const signin = (cb: () => void) = > {
    // Login operation
    setUser('user');
    // Operations performed after successful login
    setTimeout(cb, 100);
  };

  const signout = (cb: () => void) = > {
    // Exit the operation
    setUser(null);
    setTimeout(cb, 100);
  };

  return {
    user,
    signin,
    signout,
  };
};

const AuthButton = () = > {
  let history = useHistory();
  let auth = useAuth() as any;

  return auth.user ? (
    <p>Welcome!<br />User: {auth. User}<br />
      <button
        onClick={()= > {
          auth.signout(() => history.push('/'));
        }}
      >
        Sign out
      </button>
    </p>
  ) : (
    <p>You are not logged in</p>
  );
};

// Redirect to login
// If you are not authenticated, select Login
const PrivateRoute = (props: any) = > {
  // Get permission data
  let auth = useAuth() as any;
  return (
    <Route
      {. props.rest} // Render if there is a user, otherwise redirectlogin
      render={({ location}) = >
        auth.user ? (
          props.children
        ) : (
          <Redirect
            to={{
              pathname: '/login',
              state: { from: location}}} / >
        )
      }
    />
  );
};

const PublicPage = () = > {
  return <h3>Open the page</h3>;
};

const ProtectedPage = () = > {
  return <h3>Protect the page</h3>;
};

function LoginPage() {
  let history = useHistory();
  let location = useLocation() as any;
  let auth = useAuth() as any;

  let { from } = location.state || { from: { pathname: '/'}};let login = () = > {
    auth.signin(() = > {
      history.replace(from);
    });
  };

  return (
    <div>
      <p>You must be logged in to view this page {from.pathname}</p>
      <button onClick={login}>Log in</button>
    </div>
  );
}
export default function AuthExample() {
  return (
    <ProvideAuth>
      <Router>
        <div>
          <AuthButton />
          <ul>
            <li>
              <Link to="/public">The public pages</Link>
            </li>
            <li>
              <Link to="/protected">Protect pages</Link>
            </li>
          </ul>

          <Switch>
            <Route path="/public">
              <PublicPage />
            </Route>
            <Route path="/login">
              <LoginPage />
            </Route>
            <PrivateRoute path="/protected">
              <ProtectedPage />
            </PrivateRoute>
          </Switch>
        </div>
      </Router>
    </ProvideAuth>
  );
}
ReactDOM.render(<AuthExample />.document.body);
Copy the code

Redirect Redirect. If Switch is used, put Redirect behind

<Route path="/home" 
render={() = > (
  <Switch>
    <Route path="/home/page1" />
    <Route path="/home/page2" />
    <Redirect to="/home/page1" />
  </Switch>)} / >Copy the code

No matching (404).

const NoMatch = () = > {
  let location = useLocation();

  return (
    <div>
      <h3>Not with the<code>{location.pathname}</code>Corresponding page, 404</h3>
    </div>
  );
};
<Switch>.<Route path="*" component={NoMatch} />
</Switch>
Copy the code

Path =”*”, render if there is no match. If you have a bottom pocket page, you can redirect to a 404 page

    <Route render={() = > <Redirect to="/ 404" />} / >Copy the code

Sidebar

import React from "react";
import ReactDOM from "react-dom";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from "react-router-dom";

const routes = [
  {
    path: "/".exact: true.sidebar: () = > <div>home!</div>,
    main: () = > <h2>Home</h2>
  },
  {
    path: "/bubblegum".sidebar: () = > <div>bubblegum!</div>,
    main: () = > <h2>Bubblegum</h2>
  },
  {
    path: "/shoelaces".sidebar: () = > <div>shoelaces!</div>,
    main: () = > <h2>Shoelaces</h2>}];const SidebarExample = () = > {
  return (
    <Router>
      <div style={{ display: "flex}} ">
        <div
          style={{
            padding: "10px",
            width: "40% ",background: "#f0f0f0}} ">
          <ul style={{ listStyleType: "none", padding: 0}} >
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/bubblegum">Bubblegum</Link>
            </li>
            <li>
              <Link to="/shoelaces">Shoelaces</Link>
            </li>
          </ul>

          <Switch>
            {routes.map((route, index) => (
              <Route
                key={index}
                path={route.path}
                exact={route.exact}
                children={<route.sidebar />}} / >))</Switch>
        </div>

        <div style={{ flex: 1.padding: "10px}} ">
          <Switch>
            {routes.map((route, index) => (
              <Route
                key={index}
                path={route.path}
                exact={route.exact}
                children={<route.main />}} / >))</Switch>
        </div>
      </div>
    </Router>
  );
}
ReactDOM.render(<SidebarExample />.document.body);
Copy the code

Effect: