首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >componentDidMount()不是被调用的,而是只在特定情况下调用的。

componentDidMount()不是被调用的,而是只在特定情况下调用的。
EN

Stack Overflow用户
提问于 2018-06-13 00:47:12
回答 2查看 6.1K关注 0票数 6

只是提醒一下:这是一个非常奇怪的问题。我会尽我所能清楚地解释这个问题。这是发生在我的ReactJs应用程序使用React Router

我有一些组件需要来自URL的某种类型的参数。我还有不依赖于参数的组件。

如果我转到做而不是的组件需要任何参数,那么就没有任何问题了。

所以,我去我的Home,然后Account List,这两个参数都不需要任何参数,我可以来回多次,我喜欢,没有问题。

但是,如果我转到使用参数的组件,然后尝试转到另一个使用参数的组件,则会得到一个错误。该错误指示假定加载的组件react-router没有正确挂载,这会引发一个错误,告诉我子组件需要的数据丢失了。我所犯的错误很简单。他们只是简单地说:

this.props.something是必需的,但未定义

这是我在App.jsx的路线

代码语言:javascript
复制
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Route, Switch, withRouter } from 'react-router-dom';

// Import components here
// Just showing one for brevity
import Home from '../components/home/Home';

import * as appActions from '../actions/app-actions';

class App extends Component {

   constructor(props) {

      super(props);
   }

   render() {

      return(

          <div>
              <Switch>
                 <Route exact path="/member" component={Home} />
                 <Route exact path="/member/accounts" component={Accounts} />
                 <Route exact path="/member/projects" component={ProjectsList} />
                 <Route path="/member/projects/profile/:id" component={ProjectProfile} />|
                 <Route exact path="/member/tasks" component={TasksList} />
                 <Route path="/member/tasks/profile/:id" component={TaskProfile} />
              </Switch>
          </div>
      );

   }
}

function mapStateToProps(state) {

    return {
        member: state.member.memberData
    }
}

function mapDispatchToProps(dispatch) {

    return {

        actions: bindActionCreators(appActions, dispatch)
    };
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(App));

从路由中可以看出,ProjectProfileTaskProfile组件都需要ID。此外,ProjectProfileTaskProfile组件都是非常简单的父组件,它们执行两项任务:

  1. 调用API在componentDidMount()事件中加载数据
  2. 它们还根据用户的屏幕分辨率加载正确的子组件

这是我的ProjectProfile组件,TaskProfile与此基本相同。

代码语言:javascript
复制
import React, { Component } from 'react'
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

// Actions
import * as projectProfileActions from '../../../actions/project-profile-actions';

// Components
import Desktop from './ProjectProfileDesktop';
import Mobile from './ProjectProfileMobile';

class ProjectProfile extends Component {

    constructor(props) {

        super(props);
    };

    componentDidMount() {

        const id = this.props.match.params.id;
        this.props.actions.getData(id);
    }

    render() { 

        return (
                <div className="height-100 width-100">
                    <div className="height-100 width-100 row row-clean">
                    {this.props.ui.isDesktop || this.props.ui.isTablet ? <Desktop />
                        : this.props.ui.isMobile ? <Mobile />
                        : null}
                    </div>
            </div>
        );
    }
}

function mapStateToProps(state) {
    return {
        ui: state.app.window
    };
}

function mapDispatchToProps(dispatch) {

    return {
        actions: bindActionCreators(projectProfileActions, dispatch)
    };
}

export default connect(mapStateToProps, mapDispatchToProps)(ProjectProfile);

最奇怪的是,如果我一直在ProjectProfile和任何其他组件之间来回走动,并且远离TaskProfile,那么就没有问题了。我甚至可以用不同的ID点击ProjectProfile,一切都很好。只有当我转到(另一个带有参数的组件)时,这一切才会失败。我也可以对TaskProfile做同样的事情。我可以继续使用不同ID的OR来访问TaskProfile,在TaskProfile和任何没有的组件之间来回切换,没有参数,一切都很好。

只有当我先去ProjectProfile,然后尝试转到TaskProfile或者反之亦然,错误才会发生。

错误只是告诉我ProjectProfileDesktop所需的数据并不存在。

进一步的检查表明,在加载了一个带有参数的组件之后,如果我转到另一个带有参数的组件,我就不会触及第二个组件中的componentDidMount()方法。看起来,render()方法中的某些内容导致了问题,并阻止了它进入componentDidMount()。我不知道这是什么问题,因为我没有任何错误。我将一个debugger放在render()方法的顶部。虽然我没有看到一个确切的错误,但流程告诉我,肯定有什么地方出了问题。

还请注意,我正在使用withRouter。我已经看到了一些涉及withRouter的问题,但是,到目前为止,我还没有发现任何具体的问题。

我还想提到,我还有Stripe包装我的App组件。不确定这是否在这个问题上也起了作用。下面是render()在我的index.js中的样子

代码语言:javascript
复制
render(
   <Provider store={store}>
        <BrowserRouter history={browserHistory}>
          <StripeProvider apiKey="my_key">
              <App />
          </StripeProvider>
       </BrowserRouter>
   </Provider>,
   document.getElementById('root')
);

我希望你能给我一些建议。

更新:

我观察到的一种行为是,在用param加载组件之后,当我用param访问第二个组件时,我首先访问render()方法,然后在第一个createElement之后,代码跳到ReactInstrumentation.debugTool.onBeginLifeCycleTimer --参见下面的屏幕快照。

更新2:

此时,我确信这个问题不是由react-router引起的,因为我将所需的ID硬编码到组件中,这样就不需要依赖react-router或其他任何东西来获得它。

我还从TaskProfileProjectProfile组件的路由中删除了ProjectProfile参数。

我还是有同样的行为。因此,有些东西正在阻止调用componentDidMount()方法。我还尝试了componentDidUpdate(),看看它是否被调用了,但它没有被调用。我将componentWillUnmount()放在两个组件中,当我在应用程序的其他地方导航时,componentWillUnmount()会在两个组件中被调用,因此人们可能会认为这两个组件都正在卸载OK。

因此,底线是,render()方法中的某些内容正在阻止调用componentDidMount()或任何其他生命周期方法,但这只是在这种特殊情况下发生的。

我希望在这一点上有任何建议!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-19 17:22:55

在这个问题上,我已经花了一个多星期的时间把头撞在墙上,终于解决了。诚然,我认为我理解的许多概念在这个过程中变得更加清晰了。

这个错误是由于我处理"isLoading“动画逻辑的逻辑错误--是的,就那么简单和愚蠢!

我真正想在这里分享的是我为将来可能经历类似行为的每一个人所吸取的教训。

  1. 每次加载组件时都应该按componentDidMount()键。即使您来回地加载相同的组件。但是,只有在组件一开始被卸载时才可以使用componentDidMount()。如果组件未被卸载,则在随后的组件使用中不会按下componentDidMount()。因此,仔细查看您的逻辑,看看您的组件是否被卸载,如果您离开它导航。我认为查看这种情况是否发生的最简单的方法是添加componentWillUnmount()方法,其中包含一个debugger。如果您在远离组件时使用此方法,这意味着它正在卸载。
  2. 在这个过程中做了大量的研究,看看哪里是进行API调用来获取数据的最佳地方,而且很明显,componentDidMount()仍然是最好的地方。话虽如此,您可能需要在componentDidMount()中添加额外的逻辑,以确保不会进行任何不必要的API调用,因为您的数据可能仍在存储中。
  3. 在我的研究中,有人建议使用componentWillReceiveProps()方法来调用我的API来获取数据。这是个糟糕的建议!事实上,componentWillReceiveProps()componentWillUpdate()componentWillMount()方法已被废弃,因此我们不应该使用它们,原因有两个:未来的兼容性和遵循的最佳实践。下面是更多关于他们被反对的原因的信息:https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html
  4. 也许最重要的教训是:问题的原因可能比你想象的要简单得多--通常是这样--而代码中的逻辑可能是问题的根源--通常是!

希望这些教训能帮助其他人快速、无痛地找到解决方案!

票数 8
EN

Stack Overflow用户

发布于 2018-06-15 00:53:31

ComponentDidMount --当组件被挂载时,只调用一次。当您使用一个螺旋桨进行api调用时,我将使用componentWillReceiveProps和检查道具,然后进行api调用。

如果您想要you检查您的流是否使用了componentDidMount,请使用console.log检查它。

致以问候!

票数 -4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50827695

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档