React Router 第6版的简介

124 阅读4分钟

React router第6版的发布指日可待。我想现在是时候好好看看它了 ...

安装

为了使用 React Router,我们需要安装react-router-domhistory 包:

npm install history react-router-dom@next

注意,react-router-dom 仍处于测试阶段,所以我们明确定义了next 版本。

设置顶层路由

一个路由代表一个应用程序中的一个页面。我们使用React Router的JSX中的一些元素来定义所有的路由:

<BrowserRouter>
  <Routes>
    <Route path="" element={<HomePage />} />
    <Route
      path="customers"
      element={<CustomersPage />}
    />
    <Route
      path="products"
      element={<ProductsPage />}
    />
    <Route
      path="products/:id"
      element={<ProductsPage />}
    />
  </Routes>
</BrowserRouter>

BrowserRouter 元素通常是组件树中最顶层的元素,因为所有其他React Router元素都需要嵌套在它里面。BrowserRouter 为它的后代提供关于当前位置的信息,并将在页面之间执行导航。

一组路由被定义为一个Routes 元素。每个路由都被定义在它的一个Route 元素中。Route 每当位置发生变化时,Routes 找到与当前位置最匹配的path prop的子元素,并渲染element prop中定义的元素。所以,Route 元素有点像if 语句--如果它的路径与当前路径匹配,就会渲染它的元素。

Routes 在以前的React Router版本中, 被取代,一个关键的区别是,其中的 元素的排序不会像以前的 那样影响匹配。 中的匹配更加智能,其优先级基于 与 的具体程度。Switch Route Switch Routes path Route

导航

链接

一个Link 元素在被点击时将会导航到to 道具中指定的路线:

<Link to="buy">Buy</Link>

to 如果路径不是以 开始,则是呈现该路径的相对路径。如果路径以 开始,则是相对于应用程序的根。/ /

Link 是一个 元素,但不会引起服务器端的导航--导航全部发生在浏览器中。a

还有一个元素,我们可以用来做链接,叫做NavLink 。与Link 不同,NavLink 知道它是否处于活动状态:

<nav>
  <NavLink to="/" activeClassName="active" end>
    Home
  </NavLink>
  <NavLink
    to="customers"
    activeClassName="active"
  >
    Customers
  </NavLink>
  <NavLink
    to="products"
    activeClassName="active"
  >
    Products
  </NavLink>
</nav>

一个activeClassNameactiveStyle 的道具可以用来在其路由处于活动状态时为底层的a 元素设置样式。

end 道具意味着只有在当前路径是完全匹配的情况下,NavLink 才会变得活跃。在上面的例子中,如果没有end首页将永远是活动的。

编程式导航

程序性导航可以通过useNavigate 钩子来实现。该钩子返回一个函数,该函数将调用导航的路径传递给它:

const navigate = useNavigate();

一个常见的用例是表单提交:

<form
  onSubmit={(e) => {
    e.preventDefault();
    const formData = new FormData(
      e.currentTarget
    );
    // submit form
    navigate("/success");
  }}
>
  <input
    name="name"
    type="text"
    placeholder="name"
  />
  <button type="submit">Save</button>
</form>

useNavigate 钩子在第6版中是新的,并且是悬而未决的

未找到的路由

当没有其他路径与当前路径匹配时,可以定义一个未找到的路径

<Route path="/*" element={<NotFoundPage />} />

路径/* ,因为它有最弱的优先权,这意味着路由器只有在没有其他路由匹配的情况下才会接收它。

路由参数

参数可以添加到路径的冒号之后:

<Route
  path="products/:id"
  element={<ProductPage />}
/>

然后,useParams 钩子可以用来从路径中检索参数值:

const { id } = useParams();
const product = products.find(
  (p) => p.id === id
);

下属路由

你可以用Routes 元素拥有一组以上的路由。在组件树的更下方,在顶级的Routes 元素内,我们可以有一个额外的Routes 元素:

<Routes>
  <Route
    path="buy"
    element={
      <p>Thank you for buying this product!</p>
    }
  />
  <Route
    path="*"
    element={
      <Link to="buy" className="link">
        Buy
      </Link>
    }
  />
</Routes>

这是在ProductPage 内的以下路线:

<Route
  path="products/:id*"
  element={<ProductPage />}
/>

第二层路由导致一个购买按钮最初被呈现出来。当这个按钮被点击时,它被替换成这样的信息:谢谢你购买这个产品!

很好!

嵌套布局

Route 元素可以相互嵌套:

<Route
  path="products"
  element={<ProductsPage />}
>
  <Route path=":id*" element={<ProductPage />} />
</Route>

在上面的例子中,ProductsPage 将被渲染为products 的路径。当路径为products/:id. 时,ProductsPageProductPage 都将被呈现。一个Outlet 元素被用来指定ProductPageProductsPage 中的渲染位置:

<div className="product-list">
  {filteredProducts.map(({ id, name }) => (
    <Link key={id} to={`/products/${id}`}>
      {name}
    </Link>
  ))}
</div>

<Outlet />

这种方法可以产生嵌套式布局,周围的用户界面保持一致,而内部的内容在不同的路线之间变化。

搜索参数

useSearchParams 用来读取和更新搜索参数。它返回一个包含两个值的数组:当前位置的搜索参数和一个更新它们的函数:

let [
  searchParams,
  setSearchParams,
] = useSearchParams();

searchParams 是一组实用方法,允许检索特定的搜索参数。

setSearchParams 可以用来更新搜索参数:

<form
  onSubmit={(e) => {
    e.preventDefault();
    setSearchParams(
      `search=${new FormData(
        e.currentTarget
      ).get("search")}`
    );
  }}
>
  <input
    name="search"
    type="search"
    placeholder="search ..."
  />
</form>

在CodeSandbox中可以找到这些功能的一个工作实例,网址是codesandbox.io/s/react-rou…

总结

第6版中新的Routes 组件是对React Router的一个伟大补充。它的相对匹配使代码更加简洁。用嵌套的Route 元素和Outlet 做嵌套布局的能力是一个很好的提示。非常值得一看!