Route中的渲染组件不会触发其componentDidMount

时间:2017-04-18 01:18:53

标签: javascript reactjs react-router react-router-v4

不要再阅读问题,最后有解决方案

我有以下路由器,使用 react-router 4

return (
  <Router>
    <Page>
      <Route exact path="/" component={HomePage} />
      <Route path="/courses/:courseName" component={CoursePage} />
    </Page>
  </Router>
);

Page组件如下所示:

function Page(props) {
  const { children } = props;
  return (
    <div className="page">
      <SiteHeader />
      {children}
      <SiteFooter />
    </div>
  );
}

SiteHeaderSiteFooterHomePageCoursePage是纯粹的演示组成部分;他们在他们吐出标记时拿走道具。没有连接到redux商店或任何东西。 HomePageCoursePage被定义为类。

HomePageCoursePage内部,我需要使用componentDidMount挂钩,以便与DOM进行交互。

现在发生了以下奇怪的事情:

第1步:我从/网址重新加载应用

  • Page的渲染功能执行
  • HomePage的构造函数执行
  • componentDidMount的{​​{1}}执行

第2步:我导航至HomePage

  • /courses/:courseName的渲染功能执行
  • Page的{​​{1}}执行
  • componentWillUnmount的构造函数执行

请注意HomePage的{​​{1}}如何解除。这很重要,因为我需要CoursePage挂钩。

第3步:我从componentDidMount

导航回CoursePage
  • componentDidMount的渲染功能执行
  • /的构造函数执行
  • /courses/:courseName Page执行
  • HomePage的{​​{1}}执行

第4步:我再次从componentWillUnmount导航回CoursePage

  • componentDidMount的渲染功能执行
  • HomePage /courses/:courseName执行
  • /的构造函数执行
  • Page的{​​{1}}执行

备注

  • 如果在步骤1中我从componentWillUnmount而不是HomePage重新加载,而不是在CoursePage componentDidMount重新加载CoursePage,那么会发生同样的事情反之亦然。
  • 我总是丢失第2步的/courses/:courseName(第一次重定向)。之后,所有/函数都会按预期正常启动。
  • 注意步骤3和4中的粗体部分是如何以相反的顺序触发。我不确定这是否有意义。

问题

  • 为什么在第2步中,路线HomePage不会触发CoursePage方法?我错过了一些非常明显的东西,是不是神秘的知识我不知道或是否遇到过错误?

  • Bonus :在componentDidMount componentDidMount之前component触发的构造函数有什么处理,而对位不是真的当我们从componentDidMount导航到HomePage

documentation

  

当您使用路由器使用的组件(而不是渲染,下面)时   React.createElement从给定的创建一个新的React元素   零件。 这意味着如果您提供内联函数,那么您就是   每次渲染都创建一个新组件。这导致了现有的   组件卸载和新组件安装而不仅仅是   更新现有组件。

这让我的问题变得毫无意义

我找到的替代方法

在我的componentWillUnmount组件中,如果我只是按这样移动CoursePage的顺序

/

然后问题得到解决,但我认为这不是一个合适的解决方案。我真的很想知道发生了什么,因为它撕裂了我。

编辑:

为简洁起见,编辑了该问题并使用例场景更简单

更新 - 进一步观察

/courses/:coursName成为以下组件

Page

children是以下组件

function Page(props) {
  const { children } = props;
  return (
    <div className="page">
      {children} // MOVED FIRST
      <SiteHeader />
      <SiteFooter />
    </div>
  );
}

然后,所有以下配置都能正常播放,表示重定向之间没有Stub.jsx来电丢失

A)

import React from 'react';
class Stub extends React.Component {
  constructor(props) {
    super(props);
    debugger;
  }
  componentDidMount() { debugger; }
  componentWillUnmount() { debugger; }
  render() { return <div style={{ margin: '100px 0' }}><span>Hello</span></div>; }
}
export default Stub;

B)

MockPage.jsx

最终更新:

发现了问题!

问题显然是我在导入到function MockPage(props) { const { children } = props; debugger; return ( <div className="page"> <div>Hi</div> //Instead of SiteHeader {children} <div>Hi</div> //Instead of SiteFooter </div> ); } 组件的按钮中使用的componentDidMount。 Perf工具在发生的第一个重定向上抛出了一个错误,这个错误正在弄乱随后组件的生命周期钩子。这解释了这样一个事实:当我在return ( <Router> <div> <Route exact path="/" component={Stub} /> <Route path="/courses/:courseName" component={Stub} /> </div> </Router> ); 之前移动return ( <Router> <MockPage> <Route exact path="/" component={Stub} /> <Route path="/courses/:courseName" component={Stub} /> </MockPage> </Router> ); 的位置时,一切正常。感谢所有为阅读我的烦恼而烦恼的人,以及抱歉因为浪费你的时间。

1 个答案:

答案 0 :(得分:1)

使用React-route 4,你可以像这样编写页面。匹配路线的每条路线都将显示在视图中。 React-route 4不再需要props.children。

这是代码对我有用。 如果我去&#39; /&#39;然后标题,主页和页脚呈现包括DidMount。 如果我去&#39; / courses / 1&#39;然后标题,主页,课程和页脚是渲染,包括DidMount

import { BrowserRouter as Router, Route } from 'react-router-dom';
import React, { PropTypes } from 'react';
import SiteFooter from './components/App/siteFooter'
import SiteHeader from './components/App/siteHeader'
import CoursePage from './components/App/coursePage'
import HomePage from './components/App/homePage'

export default class Routes extends React.Component {
  render() {
    return (
      <Router>
        <div>
          <Route path="/" component={SiteHeader} />
          <Route path="/" component={HomePage} />
          <Route path="/courses/:courseName" component={CoursePage} />
          <Route path="/" component={SiteFooter} />
        </div>
      </Router>
    );
  }
}