1、升级V5.1指南
- 用
<Route children>
替换掉<Route render> 和/或 <Route component>
- 使用下面的hook 访问路由器状态,如当前位置和参数
- 用下面hook替换 withRouter 的所有用途
- 用 useRouteMatch 替换不在
<Switch>
内的<Route>
,或将它们包装在<Switch>
里 - 移除了
<Switch>
里面的的<Redirect>
,原因主要是不利于SEO,客户端重定向可以在Route的render里做
<Switch>
<Route path="about" render={() => <Redirect to="about-us" />} />
</Switch>
2、hooks
2.1 UseParams
V5.1之前的两种方式
import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
// BlogPost 接受一个 match prop,获取url参数
function BlogPost({ match }) {
let { slug } = match.params
// ...
}
ReactDOM.render(
<Router>
<div>
<Switch>
{/* 使用component prop */}
<Route path="/blog/:slug" component={BlogPost} />
{/* 使用 `render` prop */}
<Route
path="/posts/:slug"
render={({ match }) => <BlogPost match={match} />}
/>
</Switch>
</div>
</Router>,
document.getElementById('root')
)
说明:props 是compoent的方式和 用render的方式都可以获取URL参数,但是component方式不支持自定义参数,而render的方式虽然支持自定义传参,但还是得手动把从回调拿到的值(match)传给自己的组件.
使用useParams
import React from 'react'
import ReactDOM from 'react-dom'
import {
BrowserRouter as Router,
Route,
Switch,
useParams
} from 'react-router-dom'
function BlogPost() {
// We can call useParams() here to get the params,
// or in any child element as well!
let { slug } = useParams()
// ...
}
ReactDOM.render(
<Router>
<div>
<Switch>
{/* No weird props here, just use
regular `children` elements! */}
<Route path="/posts/:slug">
<BlogPost />
</Route>
</Switch>
</div>
</Router>,
document.getElementById('root')
)
使用小结:直接把组件作为children,路由参数可以直接从hook--useParams里取,不用再记组件配合的特殊语法。
2.2 useLocation
返回一个location对象,一个监听页面变化的例子
import { Switch, useLocation } from 'react-router-dom'
function usePageViews() {
let location = useLocation()
useEffect(
() => {
ga.send(['pageview', location.pathname])
},
[location]
)
}
function App() {
usePageViews()
return <Switch>{/* your routes here */}</Switch>
}
2.3 useHistory
返回history对象,
2.4 useRouteMatch
路由匹配hook,在外使用,比之前写法更简洁
// before
import { Route } from 'react-router-dom'
function App() {
return (
<div>
{/* ... */}
<Route
path="/BLOG/:slug/"
strict
sensitive
render={({ match }) => {
return match ? <BlogPost match={match} /> : <NotFound />
}}
/>
</div>
)
}
// after
import { useRouteMatch } from 'react-router-dom'
function App() {
let match = useRouteMatch({
path: '/BLOG/:slug/',
strict: true,
sensitive: true
})
return (
<div>
{/* ... */}
{match ? <BlogPost match={match} /> : <NotFound />}
</div>
)
}