请注意:这是一个非常奇怪的问题。我会尽力清楚地解释这个问题。这发生在我的ReactJs
应用程序中,使用React Router
.
我有一些组件需要来自 URL 的某种类型的参数。我也有不依赖于参数的组件。
如果我转到不需要任何参数的组件,则没有任何问题。
所以,我去我的Home
,然后Account List
,这两个都不需要任何参数,我可以随意来回多次,没有问题。
但是,如果我转到使用参数的组件,然后尝试转到使用参数的另一个组件,则会出现错误。该错误表明react-router
应该加载的组件未正确安装,这会引发错误,告诉我缺少子组件所需的数据。我得到的错误非常简单。他们只是说:
this.props.something 是必需的但未定义
这是我的路线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
组件都是相当简单的父组件,它们做两件事:
- 进行 API 调用以在
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
,则没有问题。我什至可以ProjectProfile
用不同的 ID打,一切正常。只有当我使用参数转到另一个组件时,这一切才会失败。我可以对TaskProfile
. 我可以继续TaskProfile
使用不同的 ID 或在没有参数的TaskProfile
任何组件之间来回切换,一切正常。
只有当我先去ProjectProfile
,然后尝试去,TaskProfile
反之亦然,才会出现错误。
错误只是告诉我所需的数据ProjectProfileDesktop
不存在。
进一步检查表明,在加载带有参数的组件后,如果我转到带有参数的另一个组件,我只是没有点击componentDidMount()
第二个组件中的方法。看起来render()
方法中的某些内容导致问题并阻止它转到componentDidMount()
. 我不确定问题是什么,因为我没有收到任何错误。我把 adebugger
放在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()
或任何其他生命周期方法被调用,但这仅在这种特殊情况下发生。
在这一点上,我将不胜感激任何建议!!!