react-router 传递参数

react-router 传递参数

React 路由第6版和第5版路由组件传递参数区别还是比较大的。V5 中传递参数主要依赖路由组件的 historylocationmatch 三个属性。

但是 V6 中,路由组件自身不具有这三个重要属性。V6 中主要依赖的是官方提供的 hooks 来解决传参问题。

传递 Parmas 参数

V5:

1
2
3
4
5
6
7
8
9
10
11
{/* 传递 params 参数 */}
<Link to={`/home/message/detail/${messageObj.id}/${messageObj.title}`}>
{ messageObj.title }
</Link>
{/* 声明接收的 params 参数 */}
<Switch>
<Route path="/home/message/detail/:id/:title" component={ Detail }/>
</Switch>

{/* 路由组件接收 params 参数 */}
const {id,title} = this.props.match.params || {}

V6:

1
2
3
4
5
6
7
8
9
10
11
12
{/*向路由传递 params 参数*/}
<Link to={`detail/${messageObj.id}/${messageObj.title}`}>
{messageObj.title}
</Link>
{/* 声明接收的 params 参数 */}
<Routes>
<Route path="detail/:id/:title" element={<Detail/>}/>
</Routes>

{/* 路由组件(函数式组件)接收 params 参数 */}
import {useParams} from "react-router-dom";
const {id, title} = useParams() || {};

V5中,路由路径必须在子路由路径前完整写上主路由路径。而 V6 中,直接写子路由路径,不能添加主路由路径,子路由前面也不能添加 /

接收参数时,V5 的 params 参数存储在路由组件的 match 属性中。而 V6 中,需要从官方提供的 useParams 中获取参数。因此,V6 中路由组件一般要使用函数式来写。

传递 Search 参数

V5

1
2
3
4
5
6
7
8
9
10
11
12
{/* 传递 search 参数 */}
<Link to={`/home/message/detail?id=${messageObj.id}&title=${messageObj.title}`}> { messageObj.title }
</Link>
{/* 声明接收的 search 参数 */}
<Routes>
<Route path="/home/message/detail" component={Detail} />
</Routes>

{/* 路由组件接收 search 参数 */}
import qs from 'querystring'
const search = this.props.location.search.slice(1)
const {id,title} = qs.parse(search) || {}

V5中,接收search只用写路径即可,不用特殊声明,因为参数已经在传递时的url中写好了。

路由组件接收 search 参数,是一段 urlencoded 格式化字符串,保存在组件的location属性中:

1
?id=01&title=message1

可以看出 search 参数就是 url 的 query 参数。

因此要先用 qs.parse() 方法将 search 参数转化成一个参数对象,才能使用:

1
2
3
4
{
id:01,
title:message1
}

在V6中,官方提供了 useLocation ,可用于获取 search 属性和随后将介绍的 state 属性,比较方便。

1
2
3
4
5
6
7
8
9
10
11
12
13
{/*向路由传递 search 参数*/}
<Link to={`detail/?id=${messageObj.id}&title=${messageObj.title}`}>
{messageObj.title}
</Link>
{/* 声明接收的 params 参数 */}
<Routes>
<Route path="detail" element={<Detail/>}/>
</Routes>

{/* 路由组件(函数式组件)接收 search 参数 */}
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{/* 传递 state 参数,必须写出成对象形式 */}
<Link to={{
path: "/home/message/detail",
state: {
id: messageObj.id,
title: messageObj.title
}
}}>{messageObj.title}</Link>
{/* 声明接收的 state 参数 */}
<Routes>
<Route path="/home/message/detail" component={Detail} />
</Routes>

{/* 路由组件接收 search 参数 */}
const { id, title } = this.props.location.state || {}

V5中,state参数传递与另两种方法不同,必须写成对象形式,作为对象赋值给 Link 的 to

V6中,则要分别设置 Link 的 tostate。从这可以看出,V6 的写法更易读,合乎直觉。

V6

1
2
3
4
5
6
7
8
9
10
11
12
13
{/* 向路由传递 state 参数 */}
<Link to={"detail"} state={{
id: messageObj.id,
title: messageObj.title
}}>{messageObj.title}</Link>
{/* 接收 search 或 state 参数 */}
<Routes>
<Route path="detail" component={Detail} />
</Routes>

{/* 路由组件(函数式组件)接收 state 参数 */}
import {useLocation} from "react-router-dom";
const {id, title} = useLocation().state || {};

尽管 state 不会出现在 url 上,但刷新浏览器参数还是会保留,路由组件不会丢失。


版权声明:本文作者为「Andy8421」.本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!