react-router 传递参数
React 路由第6版和第5版路由组件传递参数区别还是比较大的。V5 中传递参数主要依赖路由组件的 history 、 location 和 match 三个属性。
但是 V6 中,路由组件自身不具有这三个重要属性。V6 中主要依赖的是官方提供的 hooks 来解决传参问题。
传递 Parmas 参数
V5:
| {} <Link to={`/home/message/detail/${messageObj.id}/${messageObj.title}`}> { messageObj.title } </Link> {} <Switch> <Route path="/home/message/detail/:id/:title" component={ Detail }/> </Switch>
{} const {id,title} = this.props.match.params || {}
|
V6:
| {} <Link to={`detail/${messageObj.id}/${messageObj.title}`}> {messageObj.title} </Link> {} <Routes> <Route path="detail/:id/:title" element={<Detail/>}/> </Routes>
{} import {useParams} from "react-router-dom"; const {id, title} = useParams() || {};
|
V5中,路由路径必须在子路由路径前完整写上主路由路径。而 V6 中,直接写子路由路径,不能添加主路由路径,子路由前面也不能添加 /
接收参数时,V5 的 params 参数存储在路由组件的 match 属性中。而 V6 中,需要从官方提供的 useParams 中获取参数。因此,V6 中路由组件一般要使用函数式来写。
传递 Search 参数
V5
| {} <Link to={`/home/message/detail?id=${messageObj.id}&title=${messageObj.title}`}> { messageObj.title } </Link> {} <Routes> <Route path="/home/message/detail" component={Detail} /> </Routes>
{} import qs from 'querystring' const search = this.props.location.search.slice(1) const {id,title} = qs.parse(search) || {}
|
V5中,接收search只用写路径即可,不用特殊声明,因为参数已经在传递时的url中写好了。
路由组件接收 search 参数,是一段 urlencoded 格式化字符串,保存在组件的location属性中:
可以看出 search 参数就是 url 的 query 参数。
因此要先用 qs.parse() 方法将 search 参数转化成一个参数对象,才能使用:
在V6中,官方提供了 useLocation ,可用于获取 search 属性和随后将介绍的 state 属性,比较方便。
| {} <Link to={`detail/?id=${messageObj.id}&title=${messageObj.title}`}> {messageObj.title} </Link> {} <Routes> <Route path="detail" element={<Detail/>}/> </Routes>
{} import {useLocation} from "react-router-dom"; const search = useLocation().search.slice(1); const {id, title} = qs.parse(search) || {};
|
传递 State 参数
与 search 参数和 params 参数不同,state 参数不会在 url 上有所体现。他会保存在路由器 history 对象的 location 中。V5 state 直接可以在路由组件的 location 中找到,而 V6 需要通过 useLocation 获取。
V5
| {} <Link to={{ path: "/home/message/detail", state: { id: messageObj.id, title: messageObj.title } }}>{messageObj.title}</Link> {} <Routes> <Route path="/home/message/detail" component={Detail} /> </Routes>
{} const { id, title } = this.props.location.state || {}
|
V5中,state参数传递与另两种方法不同,必须写成对象形式,作为对象赋值给 Link 的 to。
V6中,则要分别设置 Link 的 to 和 state。从这可以看出,V6 的写法更易读,合乎直觉。
V6
| {} <Link to={"detail"} state={{ id: messageObj.id, title: messageObj.title }}>{messageObj.title}</Link> {} <Routes> <Route path="detail" component={Detail} /> </Routes>
{} import {useLocation} from "react-router-dom"; const {id, title} = useLocation().state || {};
|
尽管 state 不会出现在 url 上,但刷新浏览器参数还是会保留,路由组件不会丢失。