1

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?

1 Answer 1

1

It ended up being nothing to do with where the dispatch() calls were. The problem was that in my App.js, I had logic to check the localStorage for an auth token; if the token was found, there would be a dispatch(login), and if not, a dispatch(logout). I'm guessing the problem was that when the Header sent its own dispatch(logout), it caused some conflict when the components all re-rendered, leading to that error.

What I did to fix this was remove that auth check from App.js, and instead put it in my authSlice.ts file

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.