In my simple React app, I was passing a state for whether the user is logged in from a parent component down through numerous children, so that the children could have logged in vs logged out logic. The SignIn component had the form to sign the user in, while the Header component contained a button that signed the user out. This was all working.
But, I learned about Redux and wanted to implement that to clean up my states. I started with this isLoggedIn state. I also have redux-toolkit going.
So now, I have a slice that looks like this:
const initialState: AuthState = {
loggedIn: false,
authedUser: null,
}
export const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
login: (state) => {
state.loggedIn = true // Mutable change should be OK with redux-toolkit
},
logout: (state) => {
state.loggedIn = false
},
...
export const { login, logout, ... } = authSlice.actions
In the Header, I have:
...
let isLoggedIn = useSelector((state) => state.auth.loggedIn)
const dispatch = useDispatch()
...
const handleLogOut = e => {
console.log("Clicked log out");
localStorage.removeItem('token');
// setLoggedIn(false); <- this used to be a state passed down from the parent, pre-Redux
dispatch(logout());
navigate("/");
}
return (
...
<Button variant="contained" onClick={(e) => handleLogOut(e)}>
Log out
</Button>
...
)
When I click the button, I get the error Cannot update a component (Header) while rendering a different component (App). I implemented very similar code on the signin side and am getting the same error there.
My assumption is that the error has something to do with having dispatch within a function that's triggered by a button click, but I can't tell what exactly is wrong.
One thing I've tried is moving the dispatch into a useEffect. To do that, I created the useEffect with the dispatch inside in the component's function declaration, and had it trigger on a local variable, localIsLoggedIn, which is initialized as true and the click function sets to false, for example. This didn't seem to work either - the useEffect never fired.
What am I missing here?