I'm building a React application and the Header component has a Menu button that toggles the sidebar and makes a logout. In other words, it only needs to appear if the user is logged in.
I'm generating a JWT in the backend and storing it in localStorage so an auth() method can get it and decide if user is logged in. The problem is, when I login, the Header doesn't appear. If I refresh the page, it appears. And if I do the opposite, which means logging out, I get redirected to login page but the Header is still there. If I refresh the page, it stops showing itself.
I set a console.log() in the auth method and I realized it doesn't react to trigger properly.
I'm using Ant Design and the app structure is
App.tsx
|
| - views
| |
| | -ListProducts accessed by "/" route and only available when logged in
| | -Login accessed by "/login" route
|
| - components
| |
| | - Routes.tsx
|
| - routines
| |
| | - auth.ts
App.tsx
import React, { FunctionComponent, useEffect } from "react";
import './assets/styles.css';
import Routes from "./components/Routes";
import { BrowserRouter, Link } from "react-router-dom";
import { Drawer, List, PageHeader, Button } from "antd";
import { MenuOutlined, PoweroffOutlined } from "@ant-design/icons";
import auth from "./routines/auth";
const App: FunctionComponent = () => {
const [isDrawerVisible, setIsDrawerVisible] = React.useState<boolean>(false);
const routes: {id: number, name: string, route: string}[] = [
{id: 1, name: "Home", route: "/"},
{id: 2, name: "Add User", route: "/add-user"}
]
return (
<BrowserRouter>
{!auth() && <PageHeader
className = "site-page-header"
title = {
<Button
type = "text"
shape = "circle"
icon = {<MenuOutlined />}
size = "large"
onClick = {() => setIsDrawerVisible(true)}
/>}
extra = {[
<Link key = "1" to = "/logout"><Button danger icon = {<PoweroffOutlined />}>Logout</Button></Link>
]}
/>}
<Drawer
title = "Hello, 'User'!"
placement = "left"
closable
onClose = {() => setIsDrawerVisible(false)}
visible = {isDrawerVisible}
key = "left"
>
<List
itemLayout="horizontal"
dataSource={routes}
renderItem={item => (
<List.Item>
<List.Item.Meta
title={<Link to = {item.route} onClick = {() => setIsDrawerVisible(false)} style = {{display: "block"}}>{item.name}</Link>}
/>
</List.Item>
)}
/>
</Drawer>
<Routes />
</BrowserRouter>
)
}
export default App;
Routes.tsx
import React, { FunctionComponent } from "react";
import { Switch, Route, Redirect } from "react-router-dom";
import ListProducts from "../views/ListProducts";
import Login from "../views/Login";
import AddUser from "../views/AddUser";
import auth from "../routines/auth";
import Logout from "../views/Logout";
import AddProduct from "../views/AddProduct";
const PrivateRoute = ({ component: Component, ...rest}: any) => (
<Route
{...rest}
render = {props => !auth() ? (
<Component {...props} />
) : (
<Redirect to = {{pathname: "/login", state: {from: props.location}}} />
)}
/>
)
const Routes: FunctionComponent = () => {
return (
<Switch>
<Route path = "/login" component = {Login} />
<PrivateRoute exact path = "/" component = {ListProducts} />
<PrivateRoute path = "/add-product" component = {AddProduct} />
<PrivateRoute path = "/add-user" component = {AddUser} />
<Route path = "/logout" component = {Logout} />
</Switch>
)
}
export default Routes;
auth
const auth = () => {
const conditionals: boolean[] = [
localStorage.getItem("token") !== undefined,
localStorage.getItem("token") !== "",
localStorage.getItem("token") !== null
]
console.log(conditionals.includes(false); // This command isn't trigger when logging in and logging out
return conditionals.includes(false);
}
export default auth;