Search code examples
reactjsreact-hooksreact-context

component not re-rendering once user is set


I'm using Context to keep track of the user.

I've created the context:

import { createContext, useState } from "react";

export const UserContext = createContext();

export function UserProvider(props) {
    const [user, setUser] = useState(null);

    return (
        <UserContext.Provider value={{user, setUser}}>
            {props.children}
        </UserContext.Provider>
    )
}

I've wrapped my app with the UserProvider. I have a component called Appbar, that displays whether a user logged in or not. If the user is logged in, it should show a signout button and if user isn't logged in, it should show a signin button.

The Appbar component:

export default function Appbar(props) {
    const classes = useStyles();
    const {user, setUser} = useContext(UserContext);

    return (
        <AppBar className={classes.appbar} color="primary" position="static">
        <Toolbar className={classes.tab}>
        <Typography variant="h6">
            Duncc Blogs
            </Typography>
                {user ? <Button color="inherit" onClick={async () => {
                    const googleUser = signOut;
                    setUser(googleUser);
                }}>Logout</Button> : <Button color="inherit" onClick={async () => {
                        const googleUser = await signIn;
                        setUser(googleUser);
                    }} className="button">Login</Button>}
        </Toolbar>
    </AppBar>
    )
}

The problem is, when the user has successfully signed in, I want my Appbar component to re-render, so the signout button is visible. But this doesn't happen.

Can someone tell me why? Am I not using the Context API properly?


Solution

  • It turns out setUser() was being called before the user data was fetched, resulting in user being null, regardless of whether the user was signed in or not.

    I simply changed it to:

    {user ? <Button color="inherit" onClick={async () => {
                        signOut().then((value) => {
                            setUser(value);
                        })
                    }}>Logout</Button> : <Button color="inherit" onClick={async () => {
                            signIn().then((value)=>{
                                setUser(value)
                            })
                        }} className="button">Login</Button>}