I have a code that worked before but after I updated all the libraries, it started to render the App component continuously and React is throwing an Infinite Render Loop error: Minified React error #185
Here is my code:
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);
I tried to add a flag to only call the store function once considering that the user details gathering will cause the re-render, but did not work.
Also I commented out the whole cookies check without success.
If I try to comment out the line const [cookies] = useCookies([AUTHENTICATION_COOKIE]);
and it stopped rendering uncontrollably but that means I would need another way to check the cookies when the application starts.
Both store.dispatch(getUserDetailsByToken());
and i18n.changeLanguage('en');
calls are side effects, and should be part of the render.
When you call store.dispatch(getUserDetailsByToken());
it probably starts a process that causes a re-render, which triggers the dispatch again, and so on...
In addition, you should use the react-redux useDispatch
and useSelector
hooks, instead of wrapping the component with the connect
HoC, and getting dispatch
by importing the store.
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;