У меня есть код, который работал раньше, но после того, как я обновил все библиотеки, он начал непрерывно отображать компонент приложения, и React выдает ошибку бесконечного цикла рендеринга: Minified React error # 185.
Вот мой код:
import React from 'react';
import { CookiesProvider, useCookies } from 'react-cookie';
import { withTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import store from './redux/store';
import { getUserDetailsByToken } from './redux/actions/user-actions';
const AUTHENTICATION_COOKIE = 'authat';
function App(props) {
const { i18n, userDetailsLoaded } = props;
const [cookies] = useCookies([AUTHENTICATION_COOKIE]);
if (cookies[AUTHENTICATION_COOKIE] && !userDetailsLoaded) {
store.dispatch(getUserDetailsByToken());
}
i18n.changeLanguage('en');
return (
<CookiesProvider>
<div className = "app">
<Header />
<main className = "app-content full-height">
...
</main>
</div>
</CookiesProvider>
);
}
function mapStateToProps(state) {
return {
userDetailsLoaded: state.userReducers.userDetailsLoaded,
};
}
export default connect(mapStateToProps)(App);
Я попытался добавить флаг, чтобы вызывать функцию хранилища только один раз, учитывая, что сбор сведений о пользователе приведет к повторному рендерингу, но это не сработало.
Также я безуспешно закомментировал всю проверку файлов cookie.
Если я попытаюсь закомментировать строку const [cookies] = useCookies([AUTHENTICATION_COOKIE]);
, и она перестанет бесконтрольно отображаться, это означает, что мне понадобится другой способ проверки файлов cookie при запуске приложения.
🤔 А знаете ли вы, что...
React использует компонентную архитектуру для организации кода.
Вызовы store.dispatch(getUserDetailsByToken());
и i18n.changeLanguage('en');
являются побочными эффектами и должны быть частью рендеринга.
Когда вы вызываете store.dispatch(getUserDetailsByToken());
, он, вероятно, запускает процесс, вызывающий повторный рендеринг, который снова запускает отправку и так далее...
Кроме того, вам следует использовать хуки React-Redux useDispatch и useSelector вместо того, чтобы обертывать компонент connect
HoC и получать dispatch
путем импорта магазина.
import React from 'react';
import { CookiesProvider, useCookies } from 'react-cookie';
import { withTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import { getUserDetailsByToken } from './redux/actions/user-actions';
const AUTHENTICATION_COOKIE = 'authat';
function App(props) {
const dispatch = useDispatch();
const userDetailsLoaded = useSelector(state => state.userReducers.userDetailsLoaded);
const { i18n } = props;
const [cookies] = useCookies([AUTHENTICATION_COOKIE]);
const authCookie = cookies[AUTHENTICATION_COOKIE];
// an effect that gets called on mount or whenever authCookie or userDetailsLoaded change
useEffect(() => {
if (cookies[AUTHENTICATION_COOKIE] && !userDetailsLoaded) {
dispatch(getUserDetailsByToken());
}
}, [dispatch, authCookie, userDetailsLoaded]);
// a one time effect on mount
useEffect(() => {
i18n.changeLanguage('en');
}, []);
return (
<CookiesProvider>
<div className = "app">
<Header />
<main className = "app-content full-height">
...
</main>
</div>
</CookiesProvider>
);
}
export default App;