Просто на голову: это действительно странная проблема.Я сделаю все возможное, чтобы четко объяснить проблему.Это происходит в моем приложении 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
требуются идентификаторы.Кроме того, оба компонента 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
с разными идентификаторами, и все работает отлично.Все это терпит неудачу, только когда я перехожу к другому компоненту с параметром.Я могу сделать то же самое с TaskProfile
.Я могу продолжать нажимать 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
, потому что я жестко закодировал идентификатор, который мне нужен, в компоненте, чтобы я не зависел от react-router
или чего-либо еще, чтобы его получить.
Я такжеудален параметр /:id
из маршрутов для моих компонентов TaskProfile
и ProjectProfile
.
Я продолжаю в том же духе.Итак, что-то препятствует вызову метода componentDidMount()
.Я также попытался componentDidUpdate()
проверить, вызывается ли он, и это НЕТ.Я поместил componentWillUnmount()
в обоих компонентах, и когда я перемещаюсь в другом месте приложения, в обоих компонентах вызывается componentWillUnmount()
, так что можно утверждать, что оба компонента размонтированы. ОК.
Итак, суть в том, что что-то вrender()
метод запрещает вызывать componentDidMount()
или любой другой метод жизненного цикла, но это происходит только в данном конкретном случае.
Буду признателен за любые предложения на данный момент !!!