目标:
- A组件,B组件分别代表两个页面。要从A跳转到B。
- 传值。
- 传递的值可以是对象等。
- 不通过URL的参数以明文传递。
- 在浏览器中点击“返回”时,回到A页面。
不适用的方法:
A为父组件,B为子组件。在Router中只定义对应A组件的Route。然后通过B的props传值。这也是最普遍的React 父子组件的交互方式。
不适用原因:A和B共享一个route,在B中点击“返回”时会跳转到A之前的页面。使用嵌套的Route,然后使用path和通配符的形式传值。
不适用原因: path传值时,在url中可以看到传递的值。要是传递对象就更不行了。
解决方法
思路:使用嵌套的 Route,并使用 state 传值。
嵌套Route
Router定义如下:
//App.js
//定义Route
<Router history={hashHistory}>
<Route path={'/'} component={App}/>
<Route path={'a'} component={A}>
<Route path={'b'} component={B} />
</Route>
</Router>
url为/a
对应为A页面。
url为/a/b
对应为B页面,但此时B为A的子组件,页面渲染的结构如下:
<A>
<B/>
</A>
使用嵌套的Route时,一定不要忘了在父组件的render方法中添加this.props.children
,指定B组件要渲染的页面位置。否则,URL跳转成功,但是页面内容还是A的内容,不会丝毫变化。
state 传值
方法一:使用 hashHistory
这种方法需要上面定义的 Router
的history
属性为 hashHistory
。对应的A组件的代码如下:
//A.js
import { hashHistory } from 'react-router'
... ...
jump(){
//pathname:要跳转的路径
//state:要传递的值
hashHistory.push({ pathname: '/a/b', state: {test:'ssss'}});
}
方法二:使用 context
context是什么?可以看看文档结尾的参考链接。
对应的A组件的代码如下:
//A.js
export default class A extends React.Component {
//添加context参数!
constructor(props, context) {
super(props, context);
... ...
}
jump(){
//pathname:要跳转的路径
//state:要传递的值
this.context.router.push({ pathname: '/a/b', state: {test:'ssss'}});
}
render() {
return (
<div>
... ...
{this.props.children ||(.....)}
</div>
);
}
}
//注意object大小写
A.contextTypes= {
router: React.PropTypes.object.isRequired
}
调用jump
方法时,就会跳转到/a/b
对应的页面,并且传递state
。state
可以是数值字符串对象等等。
获取传递的数据
不管是hashHistory
还是context
,在B组件中,获取传递的数据时方法一样:
//B.js
this.props.location.state
Why Not To Use Context
打开React官方文档中关于Context的介绍。先说明了Context是做什么用的。
In some cases, you want to pass data through the component tree without having to pass the props down manually at every level. You can do this directly in React with the powerful “context” API.
然后就是一个大标题 Why Not To Use Context。并一条条说明问什么建议不要使用Context。
比如,如果你希望你的应用很稳定,那就不要用context。因为这是个实验性的AP,以后不一定还好用。
再比如,如果你对Redux和MobX不熟悉,那就不要用Context......对于管理state,Redux会是更好的选择。
以及,如果你不是一个经验丰富的React开发者,也别用Context......
最后还说,如果你看了这些警告还坚持要用Context,那也尽量不要大面积使用吧,如果哪天API变了也更容易升级。
好吧,本来我一开始是用的context,觉得还挺高大上。一看官方文档,那还是想替换的方案吧!后来才查到原来 hashHistory 就能简单实现,而且代码都少好多,于是赶紧把 context 都替换了。
参考链接
- React Router 使用教程: http://www.ruanyifeng.com/blog/2016/05/react_router.html?utm_source=tool.lu
- React Context: https://reactjs.org/docs/context.html
- React Router context.router 未定义错误: http://blog.csdn.net/zccz14/article/details/51619587
- this.context.router is undefined in ES6 class constructor: https://github.com/ReactTraining/react-router/issues/1059
- React Router页面传值的三种方法: http://blog.csdn.net/qq_23158083/article/details/68488831