React router入门

Posted by Wh0ami-hy on September 2, 2024

官方文档

1. 创建路由

使用对象,创建一个路由,将路径和组件做匹配

// src/Router.js
import { createBrowserRouter } from "react-router-dom";
const router = createBrowserRouter([
    { path: "/", element: <div>Hello world!</div> },
]);

export default router;

2. 路由挂载到根DOM

不使用ReactRouter时,是这样挂载的

// src/index.js
ReactDOM.render(<App />, document.getElementById("root"));

使用ReactRouter时,是这样挂载的

// src/index.js
import ReactDOM from "react-dom";
import router from "./Router";
import { RouterProvider } from "react-router-dom";

ReactDOM.render(
    <RouterProvider router={router} />,
    document.getElementById("root")
);

3. 创建全局布局

// src/layouts/MainLayout.js
const MainLayout = ()=> {
    return (
      <>
        <div id="sidebar">
          <h1>React Router</h1>
          <div>
            <form id="search-form" role="search">
              <input
                id="q"
                aria-label="Search contacts"
                placeholder="Search"
                type="search"
                name="q"
              />
              <div
                id="search-spinner"
                aria-hidden
                hidden={true}
              />
              <div
                className="sr-only"
                aria-live="polite"
              ></div>
            </form>
            <form method="post">
              <button type="submit">New</button>
            </form>
          </div>
          <nav>
            <ul>
              <li>
                <a href={`/contacts/1`}>Your Name</a>
              </li>
              <li>
                <a href={`/contacts/2`}>Your Friend</a>
              </li>
            </ul>
          </nav>
        </div>
        <div id="detail">具体页面组件</div>
      </>
    );
  }
  export default MainLayout;

把全局布局与根路径匹配

// src/Router.js
import { createBrowserRouter } from "react-router-dom";
import MainLayout from './layouts/MainLayout';

const router = createBrowserRouter([
    { path: "/", element: <MainLayout /> },
]);

export default router;

4. 处理路由不存在异常

定义异常页

// src/pages/ErrorPage.js
import { useRouteError } from "react-router-dom";

const ErrorPage = () => {
    const error = useRouteError();
    console.error(error);

    return (
        <div id="error-page">
            <h1>Oops!</h1>
            <p>Sorry, an unexpected error has occurred.</p>
            <p>
                <i>{error.statusText || error.message}</i>
            </p>
        </div>
    );
};
export default ErrorPage;

放置异常页,当访问的路径下没有匹配的组件就返回异常页

// src/Router.js
import { createBrowserRouter } from "react-router-dom";
import ErrorPage from "./pages/ErrorPage";
import MainLayout from "./layouts/MainLayout";

const router = createBrowserRouter([
    {
        path: "/",
        element: <MainLayout />,
        errorElement: <ErrorPage />
    },
]);

5. 嵌套路由

在全局布局中,加载其他组件

先把这些组件放在children数组中,和对应的路径匹配好

// src/Router.js
import { createBrowserRouter } from "react-router-dom";
import ErrorPage from "./pages/ErrorPage";
import MainLayout from "./layouts/MainLayout";
import Query from "./pages/Query";
import Hello from "./pages/Hello";

const router = createBrowserRouter([
    {
        path: "/",
        element: <MainLayout />,
        errorElement: <ErrorPage />,
        children: [
            {
                path: "query",
                element: <Query />,
            },
            {
                path: "hello",
                element: <Hello />,
            },
        ],
    },
]);

然后在全局布局的代码中,引入Outlet,把<Outlet />放在全局布局代码中相应的位置

// src/layouts/MainLayout.js
import { Outlet } from "react-router-dom";
{/* other code */}
  return (
	  {/* other code */}
      <div id="detail">
        <Outlet />
      </div>
      {/* other code */}
    </>
  );
{/* other code */}

6. 路由切换

使用<Link to>实现路由的跳转

// src/layouts/MainLayout.js
{/* other code */}
<nav>
	<ul>
		<li>
			<Link to={`query`}>Your query</Link>
		</li>
		<li>
			<Link to={`hello`}>Your Hello</Link>
		</li>
	</ul>
</nav>
{/* other code */}

7. 路由参数

形如 /users/:userId/users/123,怎么把路径中的id参数传递到组件中

8. 导航状态

使用useNavigation hook,获取导航的状态,包括 "idle" | "submitting" | "loading"

可以根据该状态,加载进度条等内容,可以配合React Content Loader 骨架屏使用

9. 默认子路由

在配置完路由后,直接访问应用,只会展示全局布局组件,不会展示具体的业务组件

<Outlet> 不会返回任何组件,因为没有任何子路由匹配,也就是说<Outlet>是根据子路由去返回组件的

const router = createBrowserRouter([
    {
        path: "/",
        element: <MainLayout />,
        errorElement: <ErrorPage />,
        children: [
            { index: true, element: <Query /> },
            {
                path: "query",
                element: <Query />,
            },
            {
                path: "hello",
                element: <Hello />,
            },
        ],
    },
]);

在children中配置{ index: true, element: <Index /> },当访问其父路由时,<Outlet> 就会返回{ index: true, element: <Index /> }中配置的组件

10. JSX Routes

使用JSX的方式创建路由和使用对象的方式创建路由效果是一样的,使用习惯不同而已


本站总访问量