路由跳转Bug:React+dva数据流页面跳转,路由发生变化但页面不刷新问题及解决方案(相同路径,不同参数)

2023-12-28 17:38:54

React+Dva.js项目中路由跳转成功(浏览器url发生变化)但页面不重新加载

1.问题描述:

在最近项目中,遇到了这个问题,如下图,项目中采用了和浏览器类似的多标签页面显示。


当我点击红色框中的按钮,希望实现页面跳转,并将被点击数据的序号作为参数,跳转传入下一个页面。

2.Bug描述:

当我在标签页中点击序号为71的数据进行路由跳转,再将序号为71的数据跳转到页面关闭后,重新点击其他数据,可以正常渲染。但是当我页面没有关闭,重新点击除序号71以外的数据,路由发生跳转,但页面仍然停留在序号为71数据跳转后的页面

3.Bug原因:

通过分析发现当点击第一个数据执行路由跳转后的页面未关闭,点击第二个数据执行路由跳转第二次传入的参数Id,虽然路由改变,但此时并未识别为一个新的页面,props中数据只有history的路由相关信息发生改变,此时并未重新执行React的生命周期,因此compontentDidMount中的dispath请求并未发出,因此数据未更新,所有的页面渲染都是建立在前一个页面数据的基础上。

4.解决方案

由于props数据中发生改变,因此我们可以使用React生命周期中的static getDerivedStateFromProps()方法,具体的使用可以看我的另一篇文章:“React新生命周期getDerivedStateFromProps的理解与使用”,不要使用componentWillReciveProps()方法,这个方法在React新的证明周期中已经被取消。
1.在getDerivedStateFromProps()方法中使用window.location.reload();
注意:使用此方法,需要在对props中的路由参数及preState中的路由参数做判断,如果不相同才可以window.location.reload(),否则,会导致dispatch请求陷入死循环。
优点:重新执行React完整生命周期
缺点:只重新加载当前标签页,其余标签页自动关闭,同时用户体验感极差,与系统整体加载页面违和。
2.在getDerivedStateFromProps()方法中,重新调用compontentDidmount中的dispatch请求。
注意:同样要注意,对props中的路由参数及preState中的路由参数做判断
优点:不会和方法1一样造成其他标签页关闭,不会与系统整体加载页面违和。如果dispatch方法有callback需要的情况下,使用这种方法会省去很多麻烦。
缺点:不会正常执行React生命周期的constructor()方法,所有的页面的渲染,都是用新的数据去替代上一个页面的数据,包括state中的数据。
3.在Models中添加subScriptions即订阅。
这个方法也是Dva.js的官方解决办法,解决原理与方法2没有太大差异,都是重新发起请求,然后用数据的变化驱动页面的渲染。为Models添加subScriptions属性,与namespace,state,*effect等同级。


具体实现代码如下:

??subscriptions: {

????setupHistory({dispatch, history}) {

??????history.listen((location) => {

????????const?{pathname} = location;

????????//在此取到新的路由

????????const?reg = /(?<path>\/testCase\/Execute\/)(?<currentTestCaseId>\d+)/g;

????????const?regCopy = /(?<path>\/testCase\/Execute\/)(?<currentTestCaseId>\d+)/g;

????????if?(reg.test(pathname)) {

????????//对路由进行正则匹配

??????????const?{groups: {currentTestCaseId}} = regCopy.exec(pathname);

????????//重新发送请求

??????????dispatch({

????????????type: 'cleanDetail',//注意,此处不需要加上该Model的NameSpace因为在Model中使用

????????????payloade:{

????????????currentTestCaseId,

??????????});

????????}

??????})

????}

??},

注意:subScriptions一旦在页面的Models中设置,当访问到该页面后,其余的所有页面都会自动调用此方法如果不对路由路径进行判断时,就会出现在用其他页面的其他参数,发送该页面请求的问题。同时,如果很多页面需要用到subScriptions,建议放到初始布局Model中,以Antd布局为例,建议放到basicdata.js的Model文件中,只需要对需要subScriptions操作的页面路径进行判断情况的增加即可,原因:刚刚说到,只要执行到这个Model文件,便创建了subScriptions,后续一直执行监听,因此我们只需要对需要的执行该操作的路径进行if和正则判断,这样不仅便于管理和维护,同时也省去了很多代码。
注意:在basicdata.js中发送dispatch请求的时候,type传入的路径就需要带上对应Model的namespace。

subScriptions简单介绍以及常见的几种监听:

model中的subscription相当于?个监听器,可以监听路由变化,?标,键盘变化,服务器连接变化,状态变化等,这样在其中就可以根据不同的变化做出相应的处理,在这个subsription中的?法名是随意定的,每次变化都会?次去调???的所有?法,所以?边会加相应的判断。

subscriptions: {

????setup({ dispatch, history }) { ?// ?法名setup可以随便命名

??????window.onresize = () => { ??//这?表?的当浏览器的页?的??变化时就会触发??的dispatch?法,这?的save就是reducers中的?法名

????????dispatch (type:"save") ?

??????}

????},

????onClick ({dispatch}) {

??????document.addEventListener('click',() => { ??//这?表?当?标点击时就会触发??的dispatch命令,这?的save就是reducers中的?法名

????????dispatch (type:"save")

??????})

????}

??},

??setupHistory({dispatch,history}){

????history.listen((location) => {

??????console.log(location) ??//这?可以获取当前变化的history路径以及参数,hash所有值,这样就可以在路由地址变化后做处理

??????....

????})

??}

文章来源:https://blog.csdn.net/m0_68271787/article/details/135212810
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。