react-router

 

组件

创建路由表

路由模式

react-router提供三种路由模式:

创建路由表

createBrowserRouter 为例:
数组的形式创建路由表:
const router = createBrowserRouter([ { path: "/", element: <Root />, children: [ { path: "dashboard", element: <Dashboard />, }, { path: "about", element: <About />, }, ], }, ]);
以组件的形式创建路由表:
const router = createBrowserRouter( createRoutesFromElements( <Route> <Route path="/" element={<Layout />}> <Route path="/" element={<Navigate to={"/home"}></Navigate>} /> <Route path="home" element={<Home />}></Route> </Route> <Route path="404" element={<Page404 />}></Route> <Route path="*" element={<Navigate to="/404" replace />} /> </Route> ) );

映射组件

无论是以数组还是组件的形式创建路由表,都需要传递两个参数:
  • path: 匹配的路由
  • element: 映射的组件
react-router通过这两个参数将组件映射到对应的路由上,当访问到匹配的路由时,就会显示对应的组
<Route path="home" element={<Home />}></Route>

RouterProvider

RouterProvider是React Router提供的一个组件,它可以将你创建的router应用到你的项目中。它有一个属性router,你可以将createBrowserRouter或其他方式创建router的函数返回的值赋给它。例如:
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( <React.StrictMode> <RouterProvider router={router}></RouterProvider> </React.StrictMode>, )
RouterProvider还有一个可选属性fallbackElement,它可以让你在路由加载过程中显示一个自定义的组件,例如一个加载动画。

路由跳转

Link组件

通过Link件进行跳转
<nav> <Link to="/invoices">Invoices</Link> <Link to="/expenses">Expenses</Link> </nav>
Link组件需要传递参数to,表示要跳转的路径。

NavLink组件

除了Link组件外,还可以通过NavLink组件来进行跳转。
NavLinkLink的区别是:NavLink是有状态的,它可以判断to匹配的路径是否是当前路径,可以由此来做一些样式处理,这在做导航栏的时候很有用。
<p> <NavLink to="/a" className={({ isActive }) => isActive ? "red" : "blue"}>A</NavLink> <NavLink to="/b" className={({ isActive }) => isActive ? "red" : "blue"}>B</NavLink> </p>

嵌套视图

Outlet组件

将子路由嵌套父路由中。
<Route path="/" element={<App />}> <Route path="home" element={<Home />}></Route> </Route>
父路由组件还应该引入 Outlet组件,这样嵌套的子组件就会在<Outlet />组件的位置上渲染。
function App() { return ( <div className="App"> <Nav /> <Outlet /> </div> ); }

布局路由

如果一个Route组件只有element属性,而没有path属性,那么这个路由将会变为布局路由。
<Route element={element={ <div> <h1>Layout</h1> <Outlet /> </div> }}> <Route path="home" element={<Home />}></Route> </Route>

404

实现404的思路很简单,首先需要创建一个404页面的路由,接下来实现一个重定向,这需要用到Navigate
<Route path="404" element={<Page404 />}></Route> <Route path="*" element={<Navigate to="/404" replace />} />

Route组件

Index路由

Index路由可以认为是父路由的默认路由,当父路由匹配,子路由都不匹配的时候,使用Index路由。
<Route path="/a" element={<A />}> <Route index element={<h2>1</h2>} /> <Route path=":id" element={<Child /> } /> </Route>
  • /a 匹配index路由
  • /a/1 匹配<Child />
如果没有index路由,当出现父路由匹配,子路由都不匹配的情况时,就会只使用父路由组件,如果此时父路由没有组件(element参数),则不会匹配到任何组件。

路由懒加载(lazy)

有时候出于bundle体积考虑,需要将路由组件拆分成单独的bundle文件,实现按需加载,这个时候就需要使用lazy。
<Route path="tabs" lazy={()=>import('./page/TabList/tabList')}></Route>
需要注意的是,此时tabList文件中组件必须导出一个名称为Component 的组件。可以更改displayName属性来改变展示的组件名。
// ✔ export function Component() { return ( <> <h1>You made it!</h1> <p>{"data"}</p> </> ); } // 更改在react-devtool中的名称 Component.displayName = "TodoList"; // ✖ export default function Component() { return ( <> <h1>You made it!</h1> <p>{'data'}</p> </> ); }

loader

路由加载器在路由呈现之前调用,要使用它需要传递一个函数,它的返回值将会被传入路由组件中,通过 useLoaderData为元素提供数据。
加载器函数有两个重要的参数:requestparams,前者是对应用程序发出的请求实例,后者是解析后的路由参数。
function handleLoader({request, params}: any) { const url = new URL(request.url) console.log(url) console.log(params) return "123"; } <Route path="tabs" loader={handleLoader} lazy={() => import("./page/TabList/tabList")} ></Route>
之后在路由组件中就可以利用useLoaderData hook来获取加载器函数的返回值了,在这个示例中是123.
export function Component() { const loaderData = useLoaderData() console.log('loaderData',loaderData) return ( <> <h1>You made it!</h1> <p>{"data"}</p> </> ); }

caseSensitive

指定匹配path是否区分大小写。为true时区分大小写,否则不区分。
<Route caseSensitive path="/wEll-aCtuA11y" />

errorElement/ErrorBoundary

如果路由组件的子孙路由组件渲染出错,则默认会展示错误堆栈,如果需要自定义展示组件,则可以指定errorElement/ErrorBoundary属性。
建议至少在根路由组件上设置一个errorElement,特别是生存环境,避免错误堆栈被公开。
如果你想自己创建 React 元素,则使用 errorElement ,否则使用ErrorBoundary , React Router 将会自动创建 React 元素。
<Route path="/" element={<App />} ErrorBoundary={ErrorPage} /> <Route path="/" element={<App />} errorElement={<ErrorPage />} />
可以在错误页面中调用useRouteError来获取错误信息,返回值是一个Error对象。
function ErrorPage() { const error = useRouteError() as Error console.log(error) return ( <div role="alert"> Error <pre> <code>{ error.message}</code> </pre> </div> ); }

Hook

路径参数和查询字符串

为路由添加路径参数和查询参数。
<p> <Link to="/a/1">A</Link> <Link to="/b?user=123&password=321">B</Link> </p>
使用路径参数需要配置路径参数名称。
<Routes> <Route path="/" element={<App />} /> <Route path="/a/:id" element={<A />} /> <Route path="/b" element={<B />} /> </Routes>
读取params
import {useParams} from "react-router-dom" export default function A(){ const params = useParams() console.log(params); return <div>A</div> }
读取searchParams
import {useSearchParams} from "react-router-dom" export default function B(){ const [searchParams,setSearchParams] = useSearchParams() console.log(searchParams.toString()); return <div>B</div> }
注意,searchParams是一个URLSearchParams对象
 

参考