链接进入react二级路由,引发的子组件二次挂载

这个问题很怪,我两个二级路由从链接进入的时候,会挂载两次子组件。

  • 从链接进入,是因为新页面在新标签页打开的。
  • 有子组件是因为公共组件提取
  • 同样的操作,有一些简单的二级路由页面,就不会挂载两次。

讲道理,没有理由有的可以,有的不可以,程序是死的,所以我断定出现这种差异,是因为代码有bug了。那么问题来了,怎么定位这个问题?

关于定位这个问题,这次吃了个大亏,说一下思路和过程吧。

  1. 第一症状是这样的,链接进入二级路由,会发出两个相同的网络请求,这个请求是放在 componentDidMount 生命周期里的,如你所知,这个生命周期是用来做初始化操作的。
    在组件的生命周期里 只会被调用一次。那么,两次请求的意思很明显,挂载了两次,到这里是很自然而然的考虑。so,在 componentWillUnmount生命周期里alert进行验证,猜想是需要验证才能确定的
  2. 确定了两次挂载后,就要考虑,哪些因素会让这个组件销毁一次?(找到销毁的原因等同于找到了挂两次的原因)
  • 【三元判断】 在react世界里,没有类似vue中 keep-alive这种保存组件状态的东西, 我管它叫做 离开即销毁。在开发中会经常用三元运算,来做显示不显示(这里没有隐藏,只有销毁)。
    so,我首先想到的也是这个可能,(至少检查过之后,可以排除这个问题)。我进行了长时间的检查(从二级路由的路由组件,到父组件,到layout布局组件,甚至祖先级的兄弟组件 都进行了检查,这个工作量有点大了,这是需要注意的地方,以后在排查问题的过程中,应该首先保证有限的因素先排查,最后才大海捞针,节省时间),结果跟你想的一样,毫无所获。那么这个三元判断的因素先排除。
  • 【路由跳转?配置?】排除了上一个,再要想到的就是路由跳转和配置方面的问题。这里的路由还是老式的 对象配置方法(对象平铺,并不能嵌套),所以把路由捋了一遍,也没有发现什么问题。那么考虑会不会是配置出了问题呢?于是我又配置了一个测试路由,,配置顺序?匹配顺序?发现也有同样的问题,搞的我一下子不知所措了。彻底懵了。再仔细想想,还有什么能影响这个呢?我想了很久,还是没有头绪。难顶。。。
  • 【安装devtools开发工具调试】 平常开发过程中,我一般是不用这个工具的,用不着,今天装上用它调试了一下,检查里 也没有发现什么问题,请求两次 ,state和props也没有异常。
  • 【点开主页,开始思考路由的嵌套】 没有头绪,还是没有头绪,然后我刷新了一会主页,发现主页始终是正常的,这一方面说明路由还是在正常工作的,另一方面,也说明我的代码结构里 还是有问题的。所以,遇到问题的时候,不能放弃,不要放弃。 我查了一些资料,没有相似的问题,我还傻兮兮的照着别人的博客多写了一个重定向,希望把父组件先加载进来,结果也是没什么用。我甚至考虑用render,children来重写这块的路由规则。
 <Switch>
              {getRoutes(match.path, getRouters(routerData,match)).map(item => (
                <Route
                  key={item.key}
                  path={item.path}
                      component={item.component}
                  exact={item.exact}
                />
              ))}
               <Redirect  to='/user/index/ioc' />
            </Switch>

在思考路由的过程中,我还对每一级的路由进行了过滤,

    const { routerData, match } = this.props;
    const  getRouters = (routerData,match) =>{
         const routes = {}
         Object.keys(routerData).map(route => {
            if(route.indexOf(match.path)>-1){
                return routes[route] = routerData[route];
            }
         })
        return routes
    }

在这个过程中,也感受到这种平铺对象操作的繁琐。但是到目前为止,关于这个bug的原因,没有一点进展,没有定位到问题所在,也没有解决方案。

  • 【柳暗花明】事情的转机出现在我6点下楼抽了一颗烟,空气中分不清是雾还是霾,我觉得 实在找不到原因,就重写一下页面,或者对项目进行一个大重构。回来之后,我把这个组件挂到主页路由上,这时候奇迹出现了,不会挂载2次了,我那个兴奋啊 , 从业以来花时间最长的bug,终于可以让我喘口气,我把这个页面放在一级路由,发现是完美运行的。 到这里,业务上的问题可以解决,但是还是没有把问题搞清楚。
    于是,我考虑二级路由的问题,我至今还是没想明白为什么二级路由,别的页面不会挂载2次,仅这两个页面挂载2次,隐约觉得,这两个页面也是有问题的。
  • 【其他尝试】发现二级路由的问题之后,由于并不想把它俩放在顶层路由,我干脆给它放到三级路由了,原始页面仍然有问题,换空白组件测试,通过了。然后一下一下的还原,发现只要引入了一个table的公共组件,就会挂载2次。
  • 【最后】最后又尝试二级路由,不显示table组件,这种情况下,发现也是正常的,所以基本排除路由的问题了。

解决方案:

  1. 提升至顶级路由。
  2. 改造table公用组件。

问题到这里算是基本找到原因了,但具体是为什么会出现这种情况,明天再尝试解决,先把过程记录下来。在react世界里,到处都充满了蝴蝶效应,有时候你的一个巨大bug,很可能就是一个逗号引起的,所以搞react开发的同学,要更认真仔细了

原文地址:https://www.cnblogs.com/chengyunshen/p/11415643.html

时间: 2024-08-26 06:36:13

链接进入react二级路由,引发的子组件二次挂载的相关文章

React 克隆组件 -- React.cloneElement(可以用来修改子组件属性值,复制子组件,添加子组件)

项目要求实现按钮级权限,简单来说就是需要通过后台数据绑定来控制前端页面哪些操作按钮需要渲染,哪些操作按钮不需要渲染, 大体的方案是: 在原有的按钮标签外再套一层按钮权限控制标签,然后每个具体的按钮对照后台给定的唯一值传入到这个"按钮权限控制"组件,然后在组件中判断该按钮该不该渲染,之中用到的一个技术点就是React.cloneElement,可以修改子元素的属性值,下面一起了解一下React.cloneElement React.cloneElement 参数:TYPE(ReactEl

React 子组件进行路由跳转

react路由跳转: 1.DOM跳转 <Link href={`/device/list`} to={`/device/add`}></Link> 2.js跳转 this.props.history.push("/device/add") 具体路由跳转细节,请自行百度 问题: 父组件: <TabPane tab="终端配置" key="1"> <A/> </TabPane> <Ta

react 父组件向子组件传递函数

这段时间一直在使用react,由于这react是单向数据绑定,总感觉有点不适用,毕竟之前一直都在使用angular,但学习还是要继续,做了一个迭代的项目,都差点忘记要总结一下这个react了,现在可以写点东西了.(react 新手,仅仅参考) 1.react一开始我更理解为是一个各种代码片段,由于之前接触了一段时间meteor,感觉有点相似.在使用之前都要在app.js中将一总的父组件通过import导入,另外在route中的path中写入链接 例如:import createHistory f

一个二级菜单引发的血案

近期发现自己css不是很好,于是又看了一遍<css权威指南>.总感觉自己抓不到重点.弃疗中...于是看看其他书.然后学妹跟我说她的二级菜单写得很乱.当时我心里就在想二级菜单,有何难?自认为10分钟能搞定.跟她要效果图并很自大的说了句“等会儿,我写个简单的”.于是血案由此引发... 二级菜单要实现的原效果图是: (如发现雷同,不是巧合,是我从别的网页上截屏下来的 ~_~).既然说了简单,肯定效果没这么精美.但是至少基本效果和原理要实现. 10分钟过去了....15分钟过去了....这个“等会儿”

React多级路由懒加载问题

React启用懒加载后,react-router使用BrowserRoute模式,二级路由页面加载其他页面时会报错“找不到相应的chunk文件”. 如页面demo/A中懒加载demo/B,会报错“react-dom.development.js:13035 Uncaught ChunkLoadError: Loading chunk B failed.”.查看network请求发现懒加载B时的js请求路径为demo/B/js/chunkName.js,而webpack打包后的统一放在了路径dis

从Angular2路由引发的前后端路由浅谈

笔者的学习进度比较慢,直到两年以前写的网站都还是以服务端为主导的,即网站的所有视图都由服务器视图模板来渲染,笔者使用的是 DotNet MVC,开发套路就是在Controller里面写Action,在Views里写对应的Action.cshtml,使用ajax发起请求已经是比较前端的事情了.这种时候由于DotNet MVC框架继承的微软风格的懒人模式,甚至不需要去知道其路由是如何实现的,给人一种感觉是只要在浏览器里敲进去Controller名与Action名,就访问到视图了. 后来笔者开始使用n

THINKPHP短链接设置方法(路由设置)

//路由设置(短链接设置)'URL_ROUTER_ON' => true,'URL_ROUTE_RULES' => array('log' => 'Login/index','admin' => 'Login/admin','reg' => 'Login/register', 'c/:id' => 'Index/index/user' '/^C_(\d+)$/' => 'Index/index/user?id=:1'), 长链接:http://localhost/

react native 之子组件和父组件之间的通信

react native开发中,为了封装性经常需要自定义组件,这样就会出现父组件和子组件,那么怎么在父组件和子组件之间相互通信呢,也就是怎么在各自界面push和pop.传值. 父组件传递给子组件: 父组件: 在主组件里面,使用通过写一个子组件的属性,直接把值或者navigator传给子组件即可.如下20行: 1 /** 2 * Sample React Native App 3 * https://github.com/facebook/react-native 4 * 父组件传递给子组件 5

夺命雷公狗---node.js---17之项目的构建在node+express+mongo的博客项目2之一,二级路由

然后我们就来开始搭建后台了... 不过后台我们可以来玩玩他的二级路由... 然后再去修改下他们的样式即可......修改方法和刚才那里的修改方法一样, 访问效果如下所示: OK,已经正常相识了