请注意:这是一个非常奇怪的问题。我会尽力清楚地解释这个问题。这是在我的ReactJs
应用程序中使用React Router
发生的。
我有一些组件需要来自URL的某种类型的参数。我也有不依赖参数的组件。
如果我转到而不是需要任何参数的组件,则没有任何问题。
因此,我先转到Home
,然后转到Account List
,这两个参数都不需要任何参数,我可以根据需要来回多次,没有问题。
但是,如果我转到使用参数的组件,然后尝试转到另一个使用参数的组件,则会收到错误消息。该错误表明应该正确加载组件react-router
并没有正确安装,这引发了一个错误,告诉我子组件所需的数据丢失。我遇到的错误非常简单。他们只是说:
this.props.something is required but undefined
这是我在
App.jsx
中的路线: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));
从路由中可以看到,
ProjectProfile
和TaskProfile
组件都需要ID。此外,ProjectProfile
和TaskProfile
组件都是相当简单的父组件,它们执行以下两项操作:componentDidMount()
事件这是我的
ProjectProfile
组件,而TaskProfile
与此几乎相同。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继续打TaskProfile
,或者在TaskProfile
和任何组件之间来回切换,而无需使用一个参数,一切正常。仅当我先进入
ProjectProfile
,然后再尝试去TaskProfile
或反之亦然时,才会发生错误。错误只是告诉我不存在
ProjectProfileDesktop
所需的数据。进一步的检查显示,在向一个带有参数的组件加载后,如果我转到另一个带有参数的组件,那么我不会碰到第二个组件中的
componentDidMount()
方法。看来render()
方法中的某些问题导致了问题,并阻止了它进入componentDidMount()
。我不确定是什么问题,因为我没有收到任何错误。我将debugger
放在render()
方法的顶部。尽管我没有看到确切的错误,但流程显示出确实有问题。另请注意,我正在使用
withRouter
。我已经看到一些涉及withRouter
的问题,但是到目前为止,我仍然找不到任何具体的问题。我还想提到,我也有Stripe提供程序包装了
App
组件。不知道这是否也在此问题中起作用。这是render()
在我的index.js
中的样子:render(
<Provider store={store}>
<BrowserRouter history={browserHistory}>
<StripeProvider apiKey="my_key">
<App />
</StripeProvider>
</BrowserRouter>
</Provider>,
document.getElementById('root')
);
我希望能对此提出一些建议。
更新:
我观察到的一种行为是,在加载带有参数的组件后,当我使用参数击中第二个组件时,我首先击中了
render()
方法,并且在第一个createElement
之后立即执行了代码,代码跳到了ReactInstrumentation.debugTool.onBeginLifeCycleTimer
-请参见下面的屏幕截图。更新2:
在这一点上,我确信问题不是由
react-router
引起的,因为我将所需的ID硬编码到组件中,因此我不依赖react-router
或其他任何东西来获取它。我还从
/:id
和TaskProfile
组件的路由中删除了ProjectProfile
参数。我仍然得到相同的行为。因此,有些事情阻止了
componentDidMount()
方法的调用。我还尝试了componentDidUpdate()
来查看它是否被调用,但不是。我在两个组件中都放置了componentWillUnmount()
,当我在应用程序中的其他位置导航时,两个组件中都调用了componentWillUnmount()
,因此人们可能会认为这两个组件都无法卸载。因此,最重要的是
render()
方法中的某些内容阻止了componentDidMount()
或任何其他生命周期方法的调用,但这仅在这种特定情况下才发生。我很乐意在此提出任何建议!
最佳答案
一个多星期以来,我一直在这个问题上犹豫不决,终于解决了。诚然,我认为我理解的许多概念在此过程中变得更加清晰。
该错误是由于我处理“isLoading”动画逻辑的逻辑错误所致-是的,如此简单而愚蠢!!!
我真正想在这里分享的是我为以后可能会遇到类似行为的每个人吸取的教训。
componentDidMount()
。即使您来回加载相同的组件。但是只有在首先卸载组件时,您才打componentDidMount()
。如果未卸载该组件,则在以后使用该组件时,您将不会命中componentDidMount()
。因此,请仔细查看您的逻辑,以查看离开组件后是否卸下了组件。我认为,查看是否发生这种情况的最简单方法是在其中添加componentWillUnmount()
的debugger
方法。如果在离开组件时单击此方法,则意味着它正在卸载。 componentDidMount()
仍然是进行此操作的最佳位置。话虽如此,您可能需要在componentDidMount()
中添加其他逻辑以确保您不会进行任何不必要的API调用,因为您的数据可能仍在您的商店中。 componentWillReceiveProps()
方法进行我的API调用以获取数据。这是不好的建议!实际上,不赞成使用componentWillReceiveProps()
,componentWillUpdate()
和componentWillMount()
方法,因此出于两个原因,我们不应该使用它们:将来的兼容性和遵循最佳实践。以下是有关为何不推荐使用它们的更多信息:https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html 希望这些类(class)能帮助其他人迅速而轻松地找到解决方案!
关于javascript - componentDidMount()不会被调用,而只会在特定情况下被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50827695/