Я создал HOC для загрузки. Он использует свойство isLoading
, чтобы решить, что показывать.
Когда я открываю страницу прямо с URL, у меня нет проблем, и все работает нормально (потому что isLoading
свойство установлено на true
по умолчанию). Проблема в том, что когда я нажимаю на ссылку (<Link ... />
), все работает не так, как ожидалось, потому что isLoading
теперь false
, потому что страница, на которой я перехожу, установила состояние на это значение.
Итак, это HOC:
import React from 'react';
export default function WithLoading(WrappedComponent, loadingDelegate) {
class LoadingComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true
};
this.loadingDelegate = loadingDelegate;
}
componentDidMount() {
loadingDelegate(this);
}
render() {
if (this.props.isLoading === true) {
return (
<div>Loading...</div>
);
} else {
return <WrappedComponent {...this.props} />;
}
}
}
return LoadingComponent;
}
И ниже компонента:
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { actionCreators } from './SurveysStore';
import WithLoading from '../LoadingHOC';
//edit/:id
class SurveyDetailRoutedComponent extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
{this.props.survey.questions.length}
</div>
);
}
}
const SurveyDetailRoutedComponentWithLoading = WithLoading(SurveyDetailRoutedComponent, (_context) => _context.props.requestSurvey(parseInt(_context.props.match.params.id)));
export default connect(
state => state.surveysReducer,
dispatch => bindActionCreators(actionCreators, dispatch)
)(SurveyDetailRoutedComponentWithLoading);
У меня ошибка в том, что survey
является нулем, потому что я пытался отрисоватьНе определено свойство распознавателя.
Проблема возникает только в том случае, если я отображаю этот компонент с помощью <Link>
, содержащегося на странице, отображаемой таким же образом .
Я пыталсяустановите isLoading=true
в маршрутизации, но у меня это не работает:
export default class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Layout>
<Route exact path='/' component={(props) => <Home {...props} />} />
<Route path='/survey/edit/:id' component={(props) => <SurveyDetailRoutedComponent {...props} isLoading={true} />} />
</Layout>
);
}
}
Само хранилище очень простое, и я думаю, что моя ошибка в том, как я справляюсь с избыточностью, потому что она выглядит какоперация маршрутизации не сбрасывает загрузку.
const resetLoading = "RESET_LOADING";
const requestSurveys = "REQUEST_SURVEYS";
const receiveSurveys = "RECEIVE_SURVEYS";
const requestSurvey = "REQUEST_SURVEY";
const receiveSurvey = "RECEIVE_SURVEY";
const initialState = { surveys: [], isLoading: true, survey: null };
export const actionCreators = {
resetLoading: () => function (dispatch, getState) {
dispatch({ type: resetLoading })
},
requestSurveys: () => async function (dispatch, getState) {
dispatch({ type: requestSurveys });
const response = await fetch(...)
const responseAsJson = await response.json();
dispatch({ type: receiveSurveys, surveys: responseAsJson.data.surveys });
},
requestSurvey: id => async function (dispatch, getState) {
dispatch({ type: requestSurvey });
const response = await fetch(...)
const responseAsJson = await response.json();
dispatch({ type: receiveSurvey, survey: responseAsJson.data.survey });
}
};
export const reducer = function(state, action) {
state = state || initialState;
switch (action.type) {
case resetLoading:
return {
...state,
isLoading: true
};
case requestSurveys:
return {
...state,
isLoading: true
};
case requestSurvey:
return {
...state,
isLoading: true
};
case receiveSurveys:
return {
...state,
isLoading: false,
surveys: action.surveys
};
case receiveSurvey:
return {
...state,
isLoading: false,
survey: action.survey
};
default:
return state;
}
}