В моем приложении реакции у меня есть страница панели инструментов, подобная этой.
import React, { useEffect } from 'react';
import { DashboardContent } from 'components';
import { Text } from 'components/ui';
import './dashboard.styles.scss';
const DashboardPage = ({ user, profile, getAuthProfileStart }: IProps) => {
console.log('reloading the page...');
useEffect(() => {
getAuthProfileStart();
}, []);
const deleteExperience = () => {
return 'Experience Deleted';
};
const deleteEducation = () => {
return 'Education Deleted';
};
const deleteAccount = () => {
return 'Account Deleted';
};
return (
<div className='dashboard'>
<div className='content'>
<Text Type='h1' className='title' text='Dashboard' />
<DashboardContent
user={user}
profile={profile}
deleteExperience={deleteExperience}
deleteEducation={deleteEducation}
deleteAccount={deleteAccount}
/>
</div>
</div>
);
};
interface IProps {
user: any;
profile: any;
getAuthProfileStart: Function;
}
export default DashboardPage;
Контейнер панели инструментов выглядит следующим образом.
import { connect } from 'react-redux';
import { compose } from 'redux';
import { WithSpinner } from 'components/ui';
import Dashboard from './dashboard.page';
import { IReduxState } from 'types/reducer.types';
import * as alertActions from 'redux/alert/alert.actions';
import * as profileActions from 'redux/profile/profle.actions';
const mapStateToProps = ({
auth: { user },
profile: { authProfile, profileFetching },
}: IReduxState) => ({
user,
profile: authProfile,
isLoading: profileFetching,
});
const actions = {
startAlert: alertActions.startAlert,
getAuthProfileStart: profileActions.getAuthProfileStart,
};
export default compose(connect(mapStateToProps, actions), WithSpinner)(Dashboard);
WithSpinner - это HO C код выглядит следующим образом.
import React from 'react';
import './with-spinner.styles.scss';
const WithSpinner = (WrappedComponent: any) => {
const Spinner = ({ isLoading, ...otherProps }: IProps) => {
return isLoading && WrappedComponent ? (
<div className='spinner-overlay'>
<div className='spinner-container' />
</div>
) : (
<WrappedComponent {...otherProps} />
);
};
return Spinner;
};
interface IProps {
isLoading: boolean;
}
export default WithSpinner;
Это действия профиля.
import { profileTypes } from 'redux/profile/profile.constants';
export const getAuthProfileStart = () => ({
type: profileTypes.GET_AUTH_PROFILE_START,
});
export const getAuthProfileSuccess = (payload: Object) => ({
type: profileTypes.GET_AUTH_PROFILE_SUCCESS,
payload,
});
export const getAuthProfileError = (payload: Object) => ({
type: profileTypes.GET_AUTH_PROFILE_ERROR,
payload,
});
Вот сага профиля.
import { call, put, select, takeLatest } from 'redux-saga/effects';
// import { alert } from 'enums/alert.enum';
// import { startAlert } from 'redux/alert/alert.actions';
import { profileTypes } from 'redux/profile/profile.constants';
import { IProfile } from 'types/profile.types';
import { IReduxState } from 'types/reducer.types';
import ProfileHttp from './profile.http';
import { getAuthProfileError, getAuthProfileSuccess } from 'redux/profile/profle.actions';
const getToken = (state: IReduxState) => state.auth.token;
export function* getAuthProfileStart() {
try {
const token = yield select(getToken);
const { data } = yield call(ProfileHttp.getAuthProfile, token);
const mappedResponse: IProfile = data;
yield put(getAuthProfileSuccess(mappedResponse));
} catch (ex) {
yield put(getAuthProfileError(ex.error));
}
}
export default function* profileSaga() {
yield takeLatest(profileTypes.GET_AUTH_PROFILE_START, getAuthProfileStart);
}
Наконец, это профиль редуктора.
import { authTypes } from 'redux/auth/auth.constants';
import { profileTypes } from 'redux/profile/profile.constants';
import { IAction } from 'types/common.types';
import { IProfileReducer } from 'types/reducer.types';
const INITIAL_STATE = {
authProfile: '',
profiles: [],
repos: [],
profileFetching: false,
error: '',
};
export default (state = INITIAL_STATE, { type, payload }: IAction) => {
switch (type) {
case profileTypes.GET_AUTH_PROFILE_START:
return startFetchingProfile(state);
case profileTypes.GET_AUTH_PROFILE_SUCCESS:
return setAuthProfileSuccess(state, payload);
case profileTypes.GET_AUTH_PROFILE_ERROR:
return setAuthProfileError(state, payload);
case authTypes.SIGN_OUT:
return signOut();
default:
return state;
}
};
const startFetchingProfile = (state: IProfileReducer) => ({
...state,
profileFetching: true,
});
const setAuthProfileSuccess = (state: IProfileReducer, payload: Object) => ({
...state,
authProfile: payload,
profileFetching: false,
error: '',
});
const setAuthProfileError = (state: IProfileReducer, payload: Object) => ({
...state,
authProfile: '',
profileFetching: false,
error: payload,
});
const signOut = () => ({
...INITIAL_STATE,
});
Здесь проблема заключается в том, что при загрузке страницы панели инструментов отображается счетчик. Но одно за другим действия getAuthProfileSuccess и getAuthProfileStart отправляются до тех пор, пока не произойдет сбой страницы. Что я здесь не так делаю? После отправки одного действия getAuthProfileSuccess я установил для profileFetching значение false, поэтому значение isLoading должно быть равно false в компоненте WithSpinner. Так что приемный компонент к HO C должен отображаться вместо счетчика.
В чем причина перезагрузки моей страницы панели инструментов?