'Why is useEffect called on conditionally rendered child component
I have a protected component I use in routes to wrap components that require a user to be logged in. I am using React Router v6. Here is component code
import React, { useEffect, useState } from 'react'
import { Navigate, useNavigate } from 'react-router-dom'
import { useDispatch, useSelector } from 'react-redux'
import { logOutUser } from './store/userSlice'
import NSF from './views/NSF'
import { refreshToken } from './api/userApi'
import { tokenCurrent } from './utils/userUtils'
const PrivateRoute = ({
component: Component,
props,
role = 'Meet Administrator',
...rest
}) => {
const navigate = useNavigate()
const dispatch = useDispatch()
const user = useSelector((state) => state.user)
const [isAuthenticated, setIsAuthenticated] = useState(null)
const [isNSF, setIsNSF] = useState(true)
useEffect(() => {
if (!tokenCurrent()) {
setIsAuthenticated(false)
dispatch(logOutUser())
navigate('/login')
} else {
if (
user.roles &&
(user.roles.includes('WebAdmin') || user.roles.includes(role))
) {
setIsNSF(false)
}
setIsAuthenticated(true)
}
refreshToken()
// eslint-disable-next-line
}, [user, dispatch, Component])
if (isAuthenticated === null) {
return <></>
}
if (isNSF && isAuthenticated) {
return <NSF />
}
return !isAuthenticated ? (
<Navigate to='/login' />
) : (
<Component {...props} {...rest} />
)
}
export default PrivateRoute
Here is a sample of how I use this component in a route:
<Routes>
<Route
path='/parents'
element={<PrivateRoute component={ParentsPage} />}
/>
</Routes>
I would not expect useEffect to be called in the "Component" if it is not rendered, but it is. That does not seem like the correct behavior. The "Component" attempts to fetch data but fails since the user is not authenticated. It isn't affecting the functionality of the page and it works correctly, but I am trying to avoid unnecessary fetch calls. The protected route pattern works, but I do not want to have to check for a user's logged in state in every component that requires the user to be authenticated which is the main reason for using the protected component as the wrapper.
Solution 1:[1]
As it turns out, it would seem, the passed in "Component", since it is provided dynamically, technically, has rendered. Still not the behavior I would expect, but I am suspecting this pattern is not optimal and, perhaps, not even the "React way". Seemed like a good idea at the time, and does work in normal cases.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | saschoff |
