0

I want the navigation bar to conditionally show 'login'or 'logout' based on if there is a token stored in local storage. I have it sort of working, but sometimes there is a delay, like I clear the token on logout but the navbar does not update until I refresh the page. I tried adding a context variable that stores a boolean value to keep track of loginStatus. I'm not sure if this is the best way? I'm still seeing that the component sometimes doesn't update until I refresh the page.

export default function Nav() {
    const { loginStatus } = useContext(AuthContext)

    const navOptions = useLoginStatus()
    //useEffect(() => {}, [loginStatus]) ?? can I do this to force the nav component to update when the loginStatus context variable changes?

    return (
        <nav className="Nav">
            <Link to="/">
                <span className="logo">
                    {' '}
                    AskifyLogo
                </span>
            </Link>
            <div className="profile-tools">
                {navOptions}
            </div>
        </nav>
    )
}

function useLoginStatus() {
    const { updateLoginStatus } = useContext(AuthContext)

    const handleLogoutClick = () => {
        updateLoginStatus(false)
        TokenService.clearAuthToken()
    }

    const renderLogoutLink = () => (
            <div className='Nav__logged-in'>
                <Link
                    onClick={handleLogoutClick}
                    to='/'>
                        Logout
                </Link>
            </div>
    );

    const renderLoginLink = () => (
            <div className='Nav__not-logged-in'>
                <Link to='/register'>
                    Register
                </Link>
                <Hyph />
                <Link to="/login">
                    Log in
                </Link>
            </div>
    );

    return TokenService.hasAuthToken() ? renderLogoutLink() : renderLoginLink()
}
LydiaHendriks
  • 303
  • 4
  • 14

2 Answers2

1

You want to update the nav bar when there is an API call (and the token expired) or when the user does not interact with the page and the token expires. To detect the latest you can use a setTimeout after receiving the token. Also, you can store the expiration time with the token and when you refresh the page reset the timeout from the saved time.

An other option is to use a middleware, like this

tiborK
  • 362
  • 1
  • 6
1

Hooks function can't return jsx elements! if you return a JSX element(s), your function automatically will transform into a component instead of a custom hook function. So you should update your hooks to this:

function useLoginStatus() {
    const { updateLoginStatus } = useContext(AuthContext)

    const handleLogoutClick = () => {
        updateLoginStatus(false)
        TokenService.clearAuthToken()
    }

    const renderLogoutLink = () => (
            <div className='Nav__logged-in'>
                <Link
                    onClick={handleLogoutClick}
                    to='/'>
                        Logout
                </Link>
            </div>
    );

    const renderLoginLink = () => (
            <div className='Nav__not-logged-in'>
                <Link to='/register'>
                    Register
                </Link>
                <Hyph />
                <Link to="/login">
                    Log in
                </Link>
            </div>
    );

    return {
     isLoggedIn: TokenService.hasAuthToken(),
     loggedInRender: renderLoginLink,
     loggedOutRender: 
    };
}

And now, you can use this function as a react custom hook function. To implement in your component:

export default function Nav() {
    const { loginStatus } = useContext(AuthContext)

    const {isLoggedIn, loggedInRender, LoggedOutRender} = useLoginStatus()
    //useEffect(() => {}, [loginStatus]) ?? can I do this to force the nav component to update when the loginStatus context variable changes?

    return (
        <nav className="Nav">
            <Link to="/">
                <span className="logo">
                    {' '}
                    AskifyLogo
                </span>
            </Link>
            <div className="profile-tools">
                {isLoggedIn ? loggedInRender() : LoggedOutRender()}
            </div>
        </nav>
    )
}
Ali Torki
  • 1,610
  • 12
  • 17