作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
内森·巴布科克的头像

Nathan Babcock

Nathan是一名前端和全栈开发人员,也是使用React简化UI/UX的专家. 作为摩托罗拉系统公司的首席设计工程师, 他编组了一个包含React的内部产品, Angular, Svelte, 本地web组件从原型到公司范围内的部署——获得了100多个,000 downloads.

Previously At

摩托罗拉解决方案
Share

React Router是事实上的React页面切换和路由解决方案. React Router是最早流行的路由器之一, 早在2014年就开始了围绕React的开源项目,并随着React一起成长为一个突出的地方 反应的生态系统.

在这个React路由器教程中,我从一个关键概念开始,解释我选择的路由库. 然后详细介绍如何创建一个简单的应用程序,其中包含足够的编程逻辑来展示各种路由特性. Lastly, 我专注于实现一个优雅的, secure, 和可重用组件,以实现最小侵入和低维护的路由解决方案. 生成的路由代码符合React的编码准则和风格,可以无缝适配任何最新版本 React application.

入门:声明式路由基础

声明式路由是React和React Router中使用的编码风格. React的声明性路由是组件,使用的管道与任何React应用程序都一样. 由于路由是组件,因此它们受益于一致的方法.

这些路由将web地址与特定的页面和其他组件关联起来, 利用React强大的渲染引擎和条件逻辑以编程方式打开和关闭路由. React中的条件路由允许我们实现应用逻辑,以确保我们的路由是正确的和充分安全的.

当然,任何路由器的性能都取决于它的库. 许多开发人员在选择库时不考虑生活质量, 但是React Router v6提供了一系列强大的功能来简化路由任务,应该是React路由解决方案的首选.

与其他路由库相比,是什么让React Router成为最好的?

  • 它有声明式路由定义(在React组件中使用JSX).
  • 这是行业标准.
  • 它提供了大量的代码示例和大量的在线教程.
  • 它提供了现代的React代码约定(使用钩子和功能组件).

使用旧版本的开发人员, React Router v5, 应该知道React Router v6的三个关键变化:

  • The 组件已重命名 .
  • A useRoutes() hook replaces react-router-config 用于将路由定义为普通对象.
  • 的每个子组件 must be a . 这可以打破以前组织和组合路由的一些方法.

本文的其余部分将探讨各种与v6兼容的模式,并以我们最终的、最优雅的路由组合作为结束. 有关从v5升级到v6的更多信息,请查看 官方移民指南.

是时候建立一个基本的React应用程序了

每个React路由教程都需要一个基本的框架来展示它想要的功能. 我们希望你的开发系统已经安装了npm. 让我们创建一个简单的 React项目与Vite-不需要单独安装Vite -它提供了我们的基本React应用程序结构, 一个独立的web服务器, 以及所有必要的依赖项:

NPM创建vite@latest redirect-app -- --模板

这个命令使用TypeScript创建我们的基本应用.

React路由基础

React Router根据关联的web地址将用户重定向到客户端内的页面. 应用程序的路由逻辑包括一般程序逻辑, 以及对未知页面的请求(例如.e.,重定向到404页面).

因为React会生成 单页面应用程序 (SPA), 这些路由模拟了老式的web应用程序,使用单独的物理或基于文件的路由. React确保最终用户保持网站和页面集合的幻觉,同时保留spa的好处,如即时页面转换. React Router库还确保浏览器历史记录仍然是可访问的,后退按钮仍然有效.

保护你的React路由

React路由通过SPA提供对特定组件的访问,从而为最终用户提供信息和功能. 我们希望用户只访问系统需求授权的特性.

而安全性在我们的React客户端中是必不可少的, 任何安全实现都应该在服务器上提供额外的(并且可以说是主要的)安全特性,以防止未经授权的客户端不法行为. 任何事情都可能发生,精明的浏览器用户可以通过浏览器开发工具调试我们的应用程序. Safety first.

一个典型的例子包括客户端管理功能. 我们希望用系统身份验证和授权管道保护这些函数. 我们应该只允许系统管理员访问潜在的破坏性系统行为.

你不应该选择的简单解决方案

有广泛的专业知识在 React developer community. 许多新手React开发人员倾向于在路由和相关的安全访问逻辑方面遵循不那么优雅的编码风格.

典型的朴素实现属性包括:

  • 在每个页面上定义路由保护.
  • Relying on useEffect React hooks 在检测到未经授权的页面访问时完成页面重定向.
  • 在重定向和路由保护逻辑执行之前,需要加载整个页面.

一个朴素的路由组件实现可能是这样的:

从react中导入{useContext, useEffect}
从react-router-dom中导入{Link, useNavigate}
import {UserContext} from../UserContext'

导出默认函数(){
  const {loggedIn} = useContext(UserContext)
  const navigation = useNavigate()

  useEffect(() => {
    //检查用户是否登录(在页面加载后)
    //如果不是,重定向到主页
    if (!loggedIn)导航(“/拒绝访问”)
  })

  return (
    
Page content...
) }

应用程序可以这样使用这个路由组件:

App() {
  return (
    
      
        {/*方法1:使用' useEffect() '作为重定向*/}
        } />
      
    
  )
}

这种方法经常被实现,但应该避免, 因为它浪费了系统性能并惹恼了我们的用户群. 朴素路由将做三件事:

  1. 负面影响我们的应用程序的性能.
    • Other useEffect hooks可能会在React中的重定向发生之前运行.
    • 我们可以看到由不必要的服务器端请求引起的系统减速. 根据运行安全检查之前遇到的逻辑块的数量,75%或更多的降级并不奇怪.
  2. 可能导致网站或页面闪烁.
    • 因为受保护的页面首先加载, 它会简单地导航到请求的web地址,但可能会重定向, 取决于页面安全逻辑.
  3. 到处复制安全路由逻辑.
    • 应用程序中每个受保护页面上的这种路由逻辑实现将导致一场维护噩梦.

使用自定义组件更好地响应路由

我们想让我们的安全路由更优雅. 有三件事可以帮助我们实现更好的实现:最小化代码维护, 集中安全路由逻辑以最小化代码影响, 提高应用程序性能. 我们实现一个自定义 ProtectedRoute 实现这些目标的组件:

从“react”中导入{ReactNode}
从react-router-dom中导入{导航}

/**
 *只允许在满足条件的情况下导航到一条路由.
 *否则,它将重定向到另一个指定的路由.
 */
导出默认功能
  condition,
  redirectTo,
  children,
}: ConditionalRouteProps): JSX.Element {
  return condition ? <>{children} : 
}

导出类型ConditionalRouteProps = {
  /**
   *如果条件为真,则创建路由.
   *例如,' condition={isLoggedIn} '或' condition={isAdmin} '
   */
  条件:布尔

  /**如果' condition '为false,重定向到的路由*/
  redirectTo:字符串

  children?: ReactNode
}

我们的应用程序代码需要调整才能使用新的 ConditionalRoute component:

App() {
  return (
    
      
       {/*方法2:使用ConditionalRoute(更好,但冗长)*/}
        最好的React路由器解决方案

我们想要一个真正史诗级的高阶实现,达到高度组件化路由安全的顶峰, 灵活的参数使用, 并且对需要路由的页面影响最小. 我们将介绍我们的编写优雅且影响最小的组件 GrandFinaleRoute:

/**具有条件路由逻辑的高阶组件*/
导出函数
  组件:FunctionComponent,
  条件:布尔,
  redirectTo:字符串
) {
  返回函数InnerComponent(props: any) {
    return condition ?  : 
  }
}

/**更具体的变化*/
导出const withLoggedIn =(组件:React.FunctionComponent) =>
  withCondition(组件,useContext (UserContext).loggedIn、/ home)

这个安全路由组件不仅满足我们的所有需求, 但也允许一个优雅和简洁的使用没有我们的页面组件:

const GrandFinaleRoute = withLoggedIn(HigherOrderComponentPage)

App() {
  return (
    
      
        {/*方法3:使用高阶组件*/}
        {/*(两全其美!) */}
        } />
      
    
  )
}

The GrandFinaleRoute 代码是否简洁、资源效率高、性能好,从而实现了我们的所有目标.

在React中实现路由

与其他代码一样,应用程序路由实现可以简单地编码,也可以优雅地编码. 我们已经对路由的基础知识进行了全面的探讨 the code 用于简单和复杂的基于React路由器的实现.

我希望最后的路由方法能与您的愿望产生共鸣,带来一个美丽的, 应用程序的低维护路由解决方案. 不管用什么方法, 通过将路由实现与我们的各种示例进行比较,您可以快速地对路由实现的有效性和安全性进行评级. React中的路由并不一定是一条上坡路. 欢迎在评论区分享你的技巧、经验和React Router的最佳实践.

Toptal Engineering博客向 Marco Sanabria 查看本文中提供的存储库和代码示例.

了解基本知识

  • React Router是用来做什么的?

    开发人员使用React Router库来管理应用程序中的屏幕流.

  • React Router值得吗?

    React Router是一个节省时间的主要工具. 它确保开发人员不必从头开始编写路由逻辑.

  • 哪个路由器最适合React/React.js?

    React Router库是开发人员使用的最流行的路由实现. 它在世界上得到了最大的支持.

  • 谁创建了React路由器??

    React Router最初是由两个关键的React团队成员开发的, 迈克尔·杰克逊和瑞安·弗洛伦斯. 目前,React Router代码库是由Remix Software维护的.

  • 如何在React中实现路由?

    React Router必须通过一个简单的“npm install”命令来安装, 之后,React中的路由用JSX元素声明式地实现.

聘请Toptal这方面的专家.
Hire Now
内森·巴布科克的头像
Nathan Babcock

Located in 芝加哥,伊利诺伊州,美国

Member since 2021年12月29日

About the author

Nathan是一名前端和全栈开发人员,也是使用React简化UI/UX的专家. 作为摩托罗拉系统公司的首席设计工程师, 他编组了一个包含React的内部产品, Angular, Svelte, 本地web组件从原型到公司范围内的部署——获得了100多个,000 downloads.

Toptal作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

Previously At

摩托罗拉解决方案

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

Toptal开发者

Join the Toptal® community.