react-router v4如何使用history控制路由跳转详解
前言
距离ReactRouterv4正式发布也已经挺久了,这周把一个React的架子做了升级,之前的路由用的还是v2.7.0版的,所以决定把路由也升级下,正好“尝尝鲜”...
江湖传言,目前官方同时维护2.x和4.x两个版本。(ヾ(。ꏿ﹏ꏿ)ノ゙咦,此刻相信机智如我的你也会发现,ReactRouterv3去哪儿了?整丢了??巴拉出锅了???敢不敢给我个完美的解释!?)事实上3.x版本相比于2.x并没有引入任何新的特性,只是将2.x版本中部分废弃API的warning移除掉而已。按照规划,没有历史包袱的新项目想要使用稳定版的ReactRouter时,应该使用ReactRouter3.x。目前3.x版本也还处于beta阶段,不过会先于4.x版本正式发布。如果你已经在使用2.x的版本,那么升级3.x将不会有任何额外的代码变动。
问题
当我们使用react-routerv3的时候,我们想跳转路径,我们一般这样处理
- 我们从react-router导出browserHistory。
- 我们使用browserHistory.push()等等方法操作路由跳转。
类似下面这样
importbrowserHistoryfrom'react-router'; exportfunctionaddProduct(props){ returndispatch=> axios.post(`xxx`,props,config) .then(response=>{ browserHistory.push('/cart');//这里 }); }
but!!问题来了,在react-routerv4中,不提供browserHistory等的导出~~
那怎么办?我如何控制路由跳转呢???
解决方法
1.使用withRouter
withRouter高阶组件,提供了history让你使用~
importReactfrom"react"; import{withRouter}from"react-router-dom"; classMyComponentextendsReact.Component{ ... myFunction(){ this.props.history.push("/some/Path"); } ... } exportdefaultwithRouter(MyComponent);
这是官方推荐做法哦。但是这种方法用起来有点难受,比如我们想在redux里面使用路由的时候,我们只能在组件把history传递过去。。
就像问题章节的代码那种场景使用,我们就必须从组件中传一个history参数过去。。。
2.使用Context
react-routerv4在Router组件中通过Contex暴露了一个router对象~
在子组件中使用Context,我们可以获得router对象,如下面例子~
importReactfrom"react"; importPropTypesfrom"prop-types"; classMyComponentextendsReact.Component{ staticcontextTypes={ router:PropTypes.object } constructor(props,context){ super(props,context); } ... myFunction(){ this.context.router.history.push("/some/Path"); } ... }
当然,这种方法慎用~尽量不用。因为react不推荐使用contex哦。在未来版本中有可能被抛弃哦。
3.hack
其实分析问题所在,就是v3中把我们传递给Router组件的history又暴露出来,让我们调用了~~
而react-routerv4的组件BrowserRouter自己创建了history,并且不暴露出来,不让我们引用了。尴尬~
我们可以不使用推荐的BrowserRouter,依旧使用Router组件。我们自己创建history,其他地方调用自己创建的history。看代码~
我们自己创建一个history
//src/history.js importcreateHistoryfrom'history/createBrowserHistory'; exportdefaultcreateHistory();
我们使用Router组件
//src/index.js import{Router,Link,Route}from'react-router-dom'; importhistoryfrom'./history'; ReactDOM.render(... , document.getElementById('root'), );
其他地方我们就可以这样用了
importhistoryfrom'./history'; exportfunctionaddProduct(props){ returndispatch=> axios.post(`xxx`,props,config) .then(response=>{ history.push('/cart');//这里 }); }
4.我非要用BrowserRouter
确实,react-routerv4推荐使用BrowserRouter组件,而在第三个解决方案中,我们抛弃了这个组件,又回退使用了Router组件。
怎么办。你去看看BrowserRouter的源码,我觉得你就豁然开朗了。
源码非常简单,没什么东西。我们完全自己写一个BrowserRouter组件,然后替换第三种解决方法中的Router组件。嘿嘿。
讲到这里也结束了,我自己目前在使用第三种方法,虽然官方推荐第一种,我觉得用着比较麻烦唉。~
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。