1

foreword

Recently completed the development of the company's new project, the related technology stack has used the latest version, and react router also uses the v6 version, so take this opportunity to sort out the difference between react router v5 and v6, as well as some new features of v6. In the case of the original project still using the old version of react router, it is not recommended to upgrade directly, and there may be many changes.

This article will also be synchronized on my Github blog

v5 upgrade v6 guide

<Switch> replace all <Routes>

v5

 <BrowserRouter>
  <Menu />

  <Switch>
    <Route component={Home} path="/home"></Route>
    <Route component={List} path="/list"></Route>
    <Route component={Detail} path="/detail"></Route>
    <Route component={Category} path="/category"></Route>
  </Switch>
</BrowserRouter>

// Category.tsx
<Switch>
  <Route component={CategoryA} path="/category/a"></Route>
  <Route component={CategoryB} path="/category/b"></Route>
</Switch>

Switch Component role: render the first location matched and as a child element <Route> or <Redirect> , it will only render a path

v6

 <BrowserRouter>
  <Menu />

  <Routes>
    <Route element={<Home />} path="/home"></Route>
    <Route element={<List />} path="/list"></Route>
    <Route element={<Detail />} path="/detail"></Route>
    <Route element={<Category />} path="/category">
      {/* children 写法嵌套子路由,path是相对路径 */}
      <Route element={<CategoryA />} path="a"></Route>
      <Route element={<CategoryB />} path="b"></Route>
    </Route>
  </Routes>
</BrowserRouter>

The main advantages of Switch compared to Routes are:

  • All Routes within <Route> and <Link> support relative routing (if it starts with / is absolute). This makes the code in <Route path> and <Link to> leaner and more predictable
  • Routing is based on the best path match, rather than traversing the selected ones in order
  • Routes can be nested in the same place without having to be scattered in different components

Notice:

  • Routes cannot be considered as a replacement for Switch . Switch feature is matching only Route component but itself is optional, you can use Route component instead of Switch . Route组件则v6 的Routes是必选的, Routes Route component, otherwise an error will be reported.

Route component properties

Route of render or component to element

 // v5
<Route component={Home} path="/home"></Route>
// v6
<Route element={<Home />} path="/home"></Route>

Simplified path format, only two dynamic placeholders are supported

  • :id dynamic parameters
  • * wildcard, can only be used at the end of path a277538e0e76222c753722cbba120413---, such as users/*

The correct way to write v6 path :

 /groups
/groups/admin
/users/:id
/users/:id/messages
/files/*
/files/:id/*

v6 path wrong spelling

 /users/:id? // ? 不满足上面两种格式
/tweets/:id(\d+) // 有正则表达式,不满足
/files/*/cat.jpg
/files-*

Enable case sensitivity for route matching caseSensitive

caseSensitive , for regular matching path Whether to enable ignore mode, that is, whether to ignore case when matching

 <Routes caseSensitive>

All path matches ignore trailing slashes on URLs

Add Outlet component

Role: usually used to render sub-routes, similar to the role of slots, used to match sub-routes element

 export default function Category() {
  return (
    <div>
      <div>
        <Link to="a">跳转 CategoryA</Link>
      </div>
      <div>
        <Link to="b">跳转 CategoryB</Link>
      </div>

      {/* 自动匹配子路由的渲染 */}
      <Outlet />
    </div>
  )
}

Link component properties

Whether the to attribute has/is the difference with the current URL

In v5, there is uncertainty if to does not start with / , depending on the current URL.

比如当前URL 是/category , <Link to="a">会渲染成<a href="/a"> ; 而当前URL /category/ ,那么又会渲染成<a href="/category/a"> .

在v6 中,无论当前URL 是/category /category/<Link to="a"><a href='/category/a'> ,即忽略URL 上的尾部斜杠Unified rule processing.

The to attribute supports relative positions and notation such as '..' and '.'

 <ul>
  <li>当前页面:CategoryA</li>
  <li>当前url:/category/a</li>
  <li>
    {/* /list */}
    <Link to="../../list">跳转到list页面</Link>
  </li>
  <li>
    {/* /category/b */}
    <Link to="../b">跳转到category/b页面</Link>
  </li>
  <li>
    {/* /category/a */}
    <Link to=".">跳转到当前路由</Link>
  </li>
</ul>

Pass the state property directly

 // v5:
<Link to={{ pathname: "/home", state: state }} />

// v6:
<Link to="/home" state={state} />

Added target attribute

 type HTMLAttributeAnchorTarget = '_self' | '_blank' | '_parent' | '_top' | (string & {})

NavLink

  • <NavLink exact> Attribute name changed to <NavLink end>
  • Removed activeStyle , activeClassName attributes
 <NavLink
  to="/messages"
- style={{ color: 'blue' }}
- activeStyle={{ color: 'green' }}
+ style={({ isActive }) => ({ color: isActive ? 'green' : 'blue' })}
>
  Messages
</NavLink>

Remove Redirect redirect component

The main reason for removal is bad for SEO

 // v5
<Redirect from="/404" to="/home" />

// v6 使用 Navigate 组件替代
<Route path="/404" element={<Navigate to="/home" replace />} />

Added useNavigate instead of useHistory

The function component can be obtained by useHistory history object, which is used for page jump navigation

 // v5
import { useHistory } from 'react-router-dom'

export default function Menu() {
  const history = useHistory()

  return (
    <div>
      <div
        onClick={() => {
          history.push('/list')
        }}
      >
        编程式路由跳转list页面
      </div>
    </div>
  )
}

// v6
import { useNavigate } from 'react-router-dom'

export default function Menu() {
  const navigate = useNavigate()

  return (
    <div>
      <div
        onClick={() => {
          navigate('/list') // 等价于 history.push
        }}
      >
        编程式路由跳转list页面
      </div>
    </div>
  )
}

Here are some other distinctions

 //v5
history.replace('/list')
// v6
navigate('/list', { replace: true })

// v5
history.go(1)
history.go(-1)

// v6
navigate(1)
navigate(-1)

Added useRoutes instead of react-router-config

useRoutes Generate the corresponding routing rules according to the routing table

useRoutes must be used in <Router>
 import { useRoutes } from 'react-router-dom'
import Home from './components/Home'
import List from './components/List'

function App() {
  const element = useRoutes([
    { path: '/home', element: <Home /> },
    { path: '/list', element: <List /> },
  ])

  return element
}

export default App

Added useSearchParams

v6 provides useSearchParams returns an array to get and set url parameters

 import { useSearchParams } from 'react-router-dom'

export default function Detail() {
  const [searchParams, setSearchParams] = useSearchParams()

  console.log('getParams', searchParams.get('name'))
  return (
    <div
      onClick={() => {
        setSearchParams({ name: 'jacky' })
      }}
    >
      当前页面:Detail 点我设置url查询参数为name=jacky
    </div>
  )
}

Not supported <Prompt>

In the old version, the Prompt component can implement page closing interception, but it is not supported in the v6 version yet. If you want to upgrade v6 from v5, you must consider it clearly.

 // v5
<Prompt
  when={formIsHalfFilledOut}
  message="Are you sure you want to leave?"
/>

Summarize

Summary of the differences between v5 and v6 at the usage level:

  • <Switch> replace all <Routes>
  • Route new feature changes

    • render and component changed to element and support nested routing
    • path supports relative paths; simplified path format, only supports two dynamic placeholders
    • Route matching case sensitivity is enabled caseSensitive
    • All path matches ignore trailing slashes on URLs /
  • Added Outlet component is used to render matched sub-routes
  • Remove Redirect redirect component, because it is not good for SEO
  • Added useNavigate replaced useHistory
  • Added useRoutes instead of react-router-config
  • Added useSearchParams to get and set url parameters

The Demo address of this article

Reference article


JackySummer
538 声望239 粉丝