上节课我们学习了如何向路由组件传递search
参数,这节课我们来学习如何向路由组件传递参数的最后一种方式,state
参数的传递。
回顾
在开始这节课的内容之前我们先对上节课来做一个简单的回顾。
search
参数不需要声明接收search
参数存放在props
中location.search
属性中search
参数传参方法和query
参数一模一样
以上便是上节课的主要内容,接下来我们开始这节课的内容。
概述
在前两节课的学习中我们学习了两种向路由组件传递参数的方法了,这节课是最后一种方法,但是我们在开始学习之前,我们要着重地说一下,state
参数和组件的state
是两码事,这个state
参数是路由的一个特殊参数,跟组件的那个state
没有任何关系,大家千万不要搞混了。
通过前两节课的学习呢,前面两种传参方法大家可能都能看出来,这两个东西在url
中都有体现出来,不管之前那两种方法中的哪一种,我们都可以在url
上面看见我们传递的参数。但是state
参数就不会在url
中体现出来,我们在url
中看不到我们传递的任何state
参数。
用法
我们现在知道了关于state
参数的两个特点
state
参数与组件的state
没有任何关系state
参数不会出现在url
中
那么我们应该如何给路由组件传递state
参数呢?首先我们在设置路由链接时就要改变我们的写法,我们要求设置路由链接时如果要传递state
参数的话,就要把to
属性写成一个对象,而不再像之前那样写成字符串就可以了。这个对象也要有两个属性:
pathname
这个就是我们的路径state
,这个state
也要是个对象,然后里面就是我们要传的参数
那么我们在设置路由链接的时候有严格要求,要将to
属性写成一个对象,那么在接收参数的时候有什么要求吗?比如像params
参数要声明接收一样。其实state
参数和search
参数一样,不需要声明接收,直接保持正常注册即可。
export default class Message extends Component { state = {...} render() { const { messageArr } = this.state return ( <div> <ul> {messageArr.map( msg => <li key={msg.id}> <Link to={{ pathname: "/home/message/details", state: { id: msg.id, title: msg.title } }}> {msg.title} </Link> </li> )} </ul> <Route path="/home/message/details" component={Details} /> </div> ) } }
我们来看一下代码,to
属性要改写成对象,那么是不是要用双花括号?然设置路径名属性和state
属性。那么传参没问题了,我们在Details
组件中应该怎么取参数呢?
按照我们的正常流程,把数据传到组件中,那肯定是存放在props
中了,只不过我们这个是路由组件,props
里面的结构比较复杂,我们要去找数据存在props
的哪个属性中了,那么我们来看一下这次我们的参数又存放在哪里了:
我们知道,match
属性是只存params
参数的,理论上应该不会存放state
参数,那么验证一下吧,果然没有。再来看location
,search
是空的,因为我们并没有传search
参数,但是紧挨着search
的下面我们发现了有一个state
属性,里面正是我们传的参数。
那就简单了,这次不像search
参数那样还要解析,这就是一个对象,直接拿来解构赋值就好了。
const data = [ { id: 1, content: "Hello world!" }, { id: 2, content: "Hello React!" }, { id: 3, content: "Hello jingxun!" }, ] export default class Details extends Component { render() { const { id, title } = this.props.location.state; const findResult = data.find(d=>d.id === id); return ( <ul> <li>ID: {id}</li> <li>TITLE: {title}</li> <li>CONTENT: {findResult.content}</li> </ul> ) } }
那么我们来看代码,正常的直接诶拿location.state
来解构赋值,后面的都是一样的操作,我就不再赘述了。那么我们来看一下效果吧:
页面正常扎实呢,数据也正常,但是浏览器的地址栏里面看不见我们传的参数。那么我来问大家一个问题,我们地址栏里面没有参数,那么我们刷新一下,会怎么样呢?
刷新了一下之后我们看到这个state
变成了undefined
。这倒也很容易理解,因为我们地址栏里什么都没有,如果刷新了之后光从路径上面来看根本不知道这个到底是点了那条message
,那么也不知道参数是什么,那么肯定就丢了嘛。
但是大家会过头来看地址栏中的url
。里面是不是有个#
?我们一直在用HashRouter
,那么我们改成BrowserRouter
的话,不论我们怎么刷新,都还会正常显示:
为什么呢?因为BrowserRouter
会一直操作浏览器的历史记录,所以说我们每一次操作BrowserRouter
其实都是知道的。所以说即便当我们刷新了,BrowserRouter
都可以通过history
来知道我们的参数到底是什么。
以上便是传递state
参数的相关内容。
总结
state
参数在设置路由链接时to
属性要写成一个对象pathname
为路由链接的路径state
为我们要传的参数,是一个对象state
参数在props.location.state
中- 当使用
BrowserRouter
时,刷新也依然可以保留住参数,但是HashRouter
不行
Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.
Link of this article:https://work.lynchow.com/article/pass_state_to_route_component/