我今天很高兴与您分享一些先进的 。 React Router 是一个令人惊叹的工具,它使我们能够在 应用程序中创建动态且流畅的导航。 React Router 技术 React 虽然它通常用于满足基本的路由需求,但有一些鲜为人知的技术可以将您的路由能力提升到一个全新的水平。 今天,我将分享一些我多年来发现的最喜欢的东西。 我们将介绍: 处理臭名昭著的 404 页面。 创建活动页面指示器以突出显示当前路线。 利用 和 挂钩。 useNavigate useLocation 当您读完本文时,您将深入掌握这些先进的 React Router 技术,并有信心将它们应用到您自己的项目中。 那么,让我们一起深入研究并提高我们的路由技能! 你准备好了吗?让我们开始吧! 处理 404 页面 在开展大型项目时,必须注意找不到的路线。我们经常将这些路由称为 ,因为当在服务器上找不到文档时,它们会返回 404。 404 路由 HTTP 状态代码 顺便说一句,如果您是猫爱好者,您可能会喜欢查看 。 http.cat 现在,让我们深入创建一个特殊的路由,只要没有其他路由与浏览器中的当前 URL 匹配,就会触发该路由。 import {BrowserRouter, Routes, Route} from "react-router-dom"; function App() { return <BrowserRouter> <Routes> <Route path="/" element={<p>Landing page</p>}></Route> <Route path="/products" element={<p>Products page</p>}></Route> <Route path="*" element={<p>404 page</p>}></Route> </Routes> </BrowserRouter> } 当访问主页 时,用户将被引导至登陆页面。导航到 页面将引导他们进入“产品”页面。但是,如果访问任何其他不对应特定路由的链接,则会显示 404 页面。 / /products 此行为背后的原因是为 404 页面实现了专门的 ,其中 path 属性设置为 。此配置确保当没有其他路由可匹配时,React Router 将独占使用该路由。 404 路由的具体位置并不重要,可以作为其不可或缺的组成部分放置在 部分内的任何位置。 <Route> * <Routes>...</Routes> 活动页面 应用程序可以实际使用路由的另一种方法是突出显示菜单中当前活动的页面。 假设您有一个包含两个链接的导航菜单: 主页 - 此链接将用户带到主页 。 / 关于 - 此链接将用户带到关于页面 。 /about 使用 React Router,当用户位于 路由时,可以自动突出显示 链接。同样,当用户位于 路线上时,您可以突出显示主页链接。最好的部分是,您无需复杂的条件即可实现此目的。 /about About / 这是让它发挥作用的简单方法: import {NavLink} from "react-router-dom"; function getClassName({isActive}) { if (isActive) { return "active"; // CSS class } } function App() { return <ul> <li> <NavLink to="/" className={getClassName}>Home</NavLink> </li> <li> <NavLink to="/about" className={getClassName}>About</NavLink> </li> </ul> } 您在上面看到的代码需要一些 CSS 才能使 类正常工作。因此,我们可以通过使当前活动页面的菜单链接显示为粗体并突出来增强它。 active .active { font-weight: bold; } 元素的 属性可以灵活地接受函数而不仅仅是字符串。当您决定使用一个函数时,它将获得一个对象作为参数,并且该对象将已经设置了 属性。为了在函数中轻松访问此属性,我们通过在参数中包含 来使用解构。 NavLink className isActive {isActive} 接下来,我们继续验证 是否具有真值。如果是这种情况,我们将返回 类名 。 isActive CSS active 当 React Router 中的当前路径与 组件的 属性匹配时, 函数将计算为布尔值。 NavLink to isActive 因此,React Router 将无缝地将 类包含在相应的 元素中,将其指示为当前活动的路由。 active <NavLink /> 较短的版本 如果您喜欢更短的方法,可以使用三元运算符来重构上面提到的代码。该运算符提供了一种使用以下格式替换 if/else 语句的方法: 。 condition ? truthy expression : falsy expression 我实际上不太使用三元运算符,因为它通常会降低代码的可读性。但是,在这种情况下使用是可以接受的。 请考虑以下示例: function getClassName({isActive}) { if (isActive) { return "active"; } else { return ""; } } 您可以用以下方法替换上面的代码: function getClassName({isActive}) { return isActive ? "active" : ""; } 您只需确保 return 语句位于三元运算符之外。当 条件为 true 时, 后面的表达式将被执行 。否则, 之后的表达式将被执行 。 isActive ? "active" : "" 现在,我们可以消除对名为 的单独函数定义的需要。相反,我们可以使用像这样的箭头函数: 。 getClassName ({isActive}) => isActive ? "active" : "" 如果您发现此更改太难以阅读,您可以像以前一样继续使用单独的函数。 最终代码如下所示: import {NavLink} from "react-router-dom"; function App() { return <ul> <li> <NavLink to="/" className={({isActive}) => isActive ? "active" : ""}>Home</NavLink> </li> <li> <NavLink to="/about" className={({isActive}) => isActive ? "active" : ""}>About</NavLink> </li> </ul> } 哦,孩子,我几乎能听到你的想法! Sojin,你已经违反了 DRY 原则,不是吗? 这只是一个例子。无需全力以赴 😀 在 Link 和 NavLink 之间进行选择:它们有何不同? 您可能已经注意到,我使用的是 而不是我们常用的朋友 。但别担心,让我解释一下原因。您会看到, 组件不允许您使用 属性的函数定义。是的,这可能会令人惊讶,但这就是您使用 时的情况。 NavLink Link <Link /> className <Link /> 我见过的一个常见错误是初级 React 开发人员尝试在 组件的 属性中使用函数定义,但这根本不起作用。 <Link /> className 如果你有兴趣,我可以写一篇关于这个主题的文章。请在评论中告诉我! 使用导航 在某些情况下,您可能需要以编程方式重新定位 React 应用程序中的页面。例如,要将访问者重定向到特定页面,您可以提交请求并等待响应。 这里有一些例子: 如果用户未登录,请将其发送至登录页面。 getLogin 请求成功完成后,将用户重定向到 。 /dashboard 这需要使用 挂钩,它返回一个函数,您可以使用该函数以编程方式将用户重定向到新路线。 useNavigate() 看一看: import React, {useEffect} from "react"; import {useNavigate} from "react-router-dom"; function HelpPage() { const navigate = useNavigate(); useEffect(() => { const isLoggedIn = window.localStorage.getItem("isLoggedIn"); if (!isLoggedIn) { navigate("/login"); } }, []); return <h2>Help page</h2>; } 使用BrowserRouter是必不可少的! 在此示例中,我们检查 localStorage 是否已分配给键 的值。如果没有,我们将使用 函数将用户重定向到 页面。 isLoggedIn navigate("/login") /login 要使其正常工作,只需记住在嵌套在 组件内的组件中使用 挂钩即可。否则,它将无法正常工作。 <BrowserRouter /> useNavigate() 例如,以下示例将不起作用: import React from "react"; import {BrowserRouter, useNavigate} from "react-router-dom"; function App() { // ❌ This breaks because the component was not wrapped by BrowserRouter, but its children are. const history = useNavigate(); return <BrowserRouter> {/* ... */} </BrowserRouter>; } 如果您尝试在 组件内使用 挂钩,您可能会遇到一些问题。这是因为除非您使用 包装 组件,否则它将无法工作。 App() useNavigate() <BrowserRouter /> App() 但别担心! 好消息是 App 内的所有子组件都会自动被 包装,因此您可以愉快地在这些子组件中使用 而不会出现任何问题。 <BrowserRouter /> useNavigate() 但是,如果您确实需要在 组件本身中使用 ,有一个简单的解决方案。您只需要创建一个包装 的父组件,并确保将 移动到该父组件内。完成此操作后,您就可以开始使用 组件中的 来满足您的需求了 💗 <App /> useNavigate() <App /> <BrowserRouter /> <App /> useNavigate() 确保可访问性和正确的链接使用 当谈到使您的网站易于访问时,请务必注意链接的结构。为了确保这一点,建议使用 元素而不是其他方法。 <Link /> 为什么? 好吧,这些元素将自动呈现为 标签,这些标签以其可 而闻名。 <a> 访问性功能 现在,这里有一个友好的提示:避免使用 提供的 方法替换普通的 元素。仅当无法使用 元素时才应使用此方法。 useNavigate() .push() <Link /> <Link /> 什么时候会发生这种情况? 通常,当您需要根据某些逻辑(例如 操作的结果)以编程方式重定向用户时。 fetch() 使用位置 如果你想每次 React Router 带你到一个新地址时执行一段代码怎么办? 您可以借助 挂钩轻松完成此任务。但在我们深入了解细节之前,让我们先探讨一些可以派上用场的场景。最常见的用例之一是将 事件发送到您的分析服务,例如 Google Analytics。 useLocation 页面浏览 不过,值得一提的是,Google Analytics 4 现在会自动处理此问题,因此您不必自己实现。 尽管如此,了解 挂钩仍然很有价值,因为您可能会发现它的其他用途。例如,您可以使用它与其他库和分析服务集成,或者根据访问的路线执行特定操作。 useLocation 可能性是无止境! 使用位置钩子 挂钩非常方便,因为它为您提供有关当前正在使用的路线的信息。 useLocation 以下是有关如何使用 useLocation 挂钩的友好指南: import {BrowserRouter, Routes, Route, useLocation} from "react-router-dom"; import {createRoot} from "react-dom/client"; function App() { const location = useLocation(); console.log(location.pathname); return <Routes> {/* routes here... */} </Routes> } createRoot(document.querySelector("#react-root")).render(<BrowserRouter><App /></BrowserRouter>); 现在,您可以通过位置变量访问路线信息。它是一个包含当前 的对象。 pathname 要找出用户当前正在浏览的路线,只需使用 。它会给你类似 、 或你设置的任何其他路由的信息。 location.pathname / /about 请记住,就像使用 挂钩一样,让您的代码在 包装的组件内运行非常重要。否则, 挂钩将无法发挥其魔力。 useNavigate <BrowserRouter /> useLocation 响应位置变化 当位置发生变化时,您可以使用 钩子来访问 React Router 中的当前 URL 路径。通过使用 挂钩包装代码并将依赖项设置为 ,只要导航到新 URL,您就可以运行特定的代码片段。 useLocation useEffect location 以下是如何执行此操作的示例: import React, {useEffect} from "react"; import {BrowserRouter, Routes, Route, useLocation} from "react-router-dom"; import {createRoot} from "react-dom/client"; function App() { const location = useLocation(); // run a piece of code on location change useEffect(() => { console.log(location.pathname); // send it to analytic, or do some conditional logic here }, [location]); return <Routes> {/* routes here... */} </Routes> } createRoot(document.querySelector("#react-root")).render(<BrowserRouter><App /></BrowserRouter>); 每当用户在导航过程中移动到新路线时, 挂钩内的代码就会运行并执行其操作。它基本上是一种确保每当位置对象发生更改时都会执行特定代码的方法。 useEffect 干得好,现在你是 React Router 专家了🥳 总而言之,本文让您对 React Router 有了更深入的了解。虽然您可能不会使用此处讨论的所有功能。不过,你能意识到它们,真是太棒了。如果您发现自己将来需要合并类似的功能,您就知道该去哪里寻找。因此,请务必保存这篇文章或为其添加书签,以便于参考。请记住,如果您有任何疑问或需要进一步帮助,请随时在 Twitter 上与我联系。我是来帮忙的!