Reputation: 8629
I have the following component:
import React, { useState, useEffect, useContext } from 'react';
import PropTypes from 'prop-types';
import { Redirect } from 'react-router-dom';
import DashboardContext from '../../contexts/DashboardContext';
import authorizeWorker from '../../workers/authorize-worker';
/**
* A protected route that calls the authorize API and redirects to login
* on fail
* @param {Function} component The component to redirect to on success
*/
const ProtectedRoute = ({ component }) => {
const [isAuthenticated, setIsAuthenticated] = useState(null);
const dashboardContext = useContext(DashboardContext);
dashboardContext.setIsDashboard(true);
const Component = component;
useEffect(() => {
authorizeWorker({})
.then(() => setIsAuthenticated(true))
.catch(() => setIsAuthenticated(false));
}, []);
if (isAuthenticated === true) {
return <Component />;
}
if (isAuthenticated === false) {
return <Redirect to="/login" />;
}
return null;
}
ProtectedRoute.propTypes = {
component: PropTypes.func
};
export default ProtectedRoute;
I use this for my router e.g.
<ProtectedRoute path="/projects" component={Projects} />
I am recently seeing a warning in the console: Warning: Cannot update a component (
App) while rendering a different component (
ProtectedRoute). To locate the bad setState() call inside
ProtectedRoute, follow the stack trace as described
. Why am I seeing this error and how can I fix it?
Upvotes: 2
Views: 2204
Reputation: 53994
The error is because on initial render phase, you render the component with setIsDashboard(true);
, usually, you want to do it on mount (useEffect
with empty dep array).
There is an initial render phase, then mount phase, see component's lifecycle diagram.
Be sure that setIsDashboard
is persistent, meaning it is created by React API (like useState
).
Or its memoized with useMemo
/useCallback
, or you will get inifite loop because on every render a new instance of setIsDashboard
will be created and the dep array ([setIsDashboard]
) will cause another execution.
const ProtectedRoute = ({ component }) => {
const { setIsDashboard } = useContext(DashboardContext);
// Make sure `setIsDashboard` persistant
useEffect(() => {
setIsDashboard(true);
}, [setIsDashboard]);
...
};
Upvotes: 3
Reputation: 11309
The error is because you can't set state when you are rendering:
dashboardContext.setIsDashboard(true);
is probably the problem.
You don't post your stack trace or line numbers so it's hard to tell exactly what the issue is:
https://stackoverflow.com/help/minimal-reproducible-example
Upvotes: 0