Issue
I am quite new to react and JavaScript. I am trying to make a dynamic navigation bar that shows certain links if the user is logged in or logged out. I want to base it off of if the JWT token is present or not. I am stuck on how to implement 'checking if a user is logged in using tokens' into my Navbar function, so the boolean works to use one component if public or one component if logged in.
import "./navbar.css"
import NavLoggedIn from "./navLoggedIn"
import NavPublic from "./navPublic"
const Navbar = () => {
const token = window.localStorage.getItem("token");
return (
<>
{ token === null ? <NavPublic /> : <NavLoggedIn /> }
</>
);
};
export default Navbar;
import "./navbar.css"
const NavLoggedIn = () => {
return (
<>
<nav className="nav">
<a href="/" className="site-title">Acebook</a>
<li>
<a href="/">profile</a>
</li>
<li>
<a href="/posts">posts</a>
</li>
<li>
<a href="/login">logout</a>
</li>
</nav>
</>
);
}
export default NavLoggedIn ;
import "./navbar.css"
const NavPublic = () => {
return (
<>
<nav className="nav">
<a href="/" className="site-title">Acebook</a>
<ul>
<li>
<a href="/signup">signup</a>
</li>
<li>
<a href="/login">login</a>
</li>
</ul>
</nav>
</>
);
}
export default NavPublic;
Solution
So the problem with the current approach is that the NavBar
component only checks the token in localStorage
when it mounts. It's "unaware" of subsequent changes to the authentication status.
I propose an alternative solution in which we use the Context API. We can start by introducing a new component:
import React, { createContext, useState } from 'react'
const AuthenticationContext = createContext({})
const AuthenticationProvider = ({ children }) => {
const [isLoggedIn, setIsLoggedIn] = useState(false)
return (
<AuthenticationContext.Provider value={{isLoggedIn, setIsLoggedIn}}>
{children}
</AuthenticationContext.Provider>
)
}
export default AuthenticationProvider
This component has a named export, which exports a context and a default export which exports the provider. We can wrap the entire app in the provider. Assuming the root component is called <App/>
, we can do this:
<AuthenticationProvider>
<App/>
</AuthenticationProvider>
Now, in any component in your app that you can access this context like so:
import React, { useContext } from 'react'
import { AuthenticationContext } from 'path/to/AuthenticationProvider'
const { isLoggedIn, setIsLoggedIn} = useContext(AuthenticationContext)
In your login function you would call setIsLoggedIn(true)
and in your logout function you would call setIsLoggedIn(false)
. Within your NavBar
component you would check the value of isLoggedIn
. The NavBar
component should "see" whenever the value changes and render the correct Nav component.
Answered By - Neil Girardi
Answer Checked By - - Dawn Plyler (ReactFix Volunteer)