0

Here in this code, I'm using navbar based on condition if the user is logged in(if the user info is stored in localstorage), except login component, I'm rendering the navbar component. But after successful login it in the respective component, at the first time routing, it is not showing navbar at top, it is showing only if I refresh the page. I tried this solution, But this solution didnt work for me components are below. Thank You

Index.js

    import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import 'bootstrap/dist/css/bootstrap.min.css';
import { BrowserRouter } from 'react-router-dom'
ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter><App /></BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);
reportWebVitals();

App.js

import { React, useEffect,useState } from 'react'
import { BrowserRouter as Router, Switch, Route,withRouter } from 'react-router-dom'
import Login from './components/login/Login'
import Admin from './components/admin/Admin'
import ProtectedRoute from './ProtectedRoute'
import Navbar from './components/Navbar/Navbar'
const App = () => {
  const [nb, setNb] = useState(false)
  const checkIsAuth = () => {
    const _isAuth = localStorage.getItem('isAuth');
    const _user = localStorage.getItem('user');
    const _password = localStorage.getItem('password');
    if (_isAuth && _user && _password) setNb(true)
  }
  useEffect(() => {
    checkIsAuth()
  }, [])
  return (
    <div style={{ textAlign: "center" }}>
      {nb && <Navbar />}
        <Switch>
          <ProtectedRoute exact path={`/admin`} component={Admin} />
          <Route exact path="/" component={Login} />
        </Switch>
    </div>
  );
}

export default withRouter(App);

Login.js

import { React, useEffect, useState } from 'react'
import { useHistory } from 'react-router-dom'
import { Form, Button } from 'react-bootstrap'
import { withRouter } from 'react-router-dom'
const Login = () => {
    const history = useHistory()
    const [userName, setUserName] = useState('')
    const [password, setPassword] = useState('')
    const submit = () => {
        if ((userName === 'admin' || userName === 'operator' || userName === 'supervisor') && password === 'welcome') {
            localStorage.setItem('user', userName)
            localStorage.setItem('isAuth', true)
            localStorage.setItem('password', password)
            setPassword('');
            setUserName('');
            history.push(`/${userName}`)
        }
        else if (!((userName === 'admin' || userName === 'operator' || userName === 'supervisor') && password === 'welcome')) {
            alert("Invalid Credentials")
            setPassword('')
            setUserName('')
            history.push(`/`)
        }
    }
    const checkIsAuth = () => {
        const _isAuth = localStorage.getItem('isAuth');
        const _user = localStorage.getItem('user');
        const _password = localStorage.getItem('password');
        if (_isAuth && _user && _password) history.push(`/${localStorage.getItem('user')}`)
    }
    useEffect(() => {
        checkIsAuth()
    }, [])
    return (
        <div>
            <Form>
                <Form.Group className="mb-3" controlId="formBasicEmail">
                    <Form.Label>Username</Form.Label>
                    <Form.Control type="text" placeholder="Enter Username" onChange={e => setUserName(e.target.value)}
                    />
                </Form.Group>
                <Form.Group className="mb-3" controlId="formBasicPassword">
                    <Form.Label>Password</Form.Label>
                    <Form.Control type="password" placeholder="Password" onChange={e => setPassword(e.target.value)} />
                </Form.Group>
                <Button variant="primary" onClick={submit}>
                    Submit
                </Button>
            </Form>
        </div>
    )
}

export default withRouter(Login)

ProtectedRoute.js

import React from 'react'
import { Route, Redirect } from 'react-router-dom'
const ProtectedRoute = ({ component: Component, ...rest }) => {
    const checkIsAuth = () => {
        const _isAuth = localStorage.getItem('isAuth');
        const _user = localStorage.getItem('user');
        const _password = localStorage.getItem('password');
        let res = { isAuth: !!_isAuth, user: _user, password: _password }
        return res
    }
    return (
        <Route {...rest}
            render={(props) => {
                if (checkIsAuth().isAuth && checkIsAuth().user && checkIsAuth().password) {
                    return <Component />
                }
                else {
                    return <Redirect to={{ pathname: '/', state: { from: props.location } }} />
                }
            }}
        />
    )
}

export default ProtectedRoute

Admin.js

    import React from 'react'
import { withRouter } from 'react-router-dom'
const Admin = () => {
    return (
        <div>
            Admin
        </div>
    )
}

export default withRouter(Admin)
rakshit
  • 49
  • 4
  • You should be using some local component state in `App` to hold the auth state and pass state/callbacks to the children components rendered by routes, or use a React context or redux to hold a global app state. You should initialize state from localStorage and only persisting state updates back to localStorage. Your components are all doing too much localStorage micro-management. The issue here is that `App` only checks localStorage when it mounts, which is why the page reload is necessary to reread the updated values from localStorage. – Drew Reese Aug 09 '21 at 05:23

1 Answers1

0

Changes Required

App.js

import { React, useEffect,useState } from 'react'
import { BrowserRouter as Router, Switch, Route,withRouter } from 'react-router-dom'
import Login from './components/login/Login'
import Admin from './components/admin/Admin'
import ProtectedRoute from './ProtectedRoute'
import Navbar from './components/Navbar/Navbar'
const App = () => {
  const [nb, setNb] = useState(false)
  const checkIsAuth = () => {
    const _isAuth = localStorage.getItem('isAuth');
    const _user = localStorage.getItem('user');
    const _password = localStorage.getItem('password');
    if (_isAuth && _user && _password) setNb(true)
  }
  useEffect(() => {
    checkIsAuth()
  }, [])
  return (
    <div style={{ textAlign: "center" }}>
      {nb && <Navbar />}
        <Switch>
          <ProtectedRoute exact path={`/admin`} component={Admin} />
          <Route exact path="/" render={(routerProps) => <Login setNb={setNb}/>} />
        </Switch>
    </div>
  );
}

export default withRouter(App);

Login.js

import { React, useEffect, useState } from 'react'
import { useHistory } from 'react-router-dom'
import { Form, Button } from 'react-bootstrap'
import { withRouter } from 'react-router-dom'
const Login = ({setNb}) => {
    const history = useHistory()
    const [userName, setUserName] = useState('')
    const [password, setPassword] = useState('')
    const submit = () => {
        if ((userName === 'admin' || userName === 'operator' || userName === 'supervisor') && password === 'welcome') {
            localStorage.setItem('user', userName)
            localStorage.setItem('isAuth', true)
            localStorage.setItem('password', password)
            setPassword('');
            setUserName('');
            history.push(`/${userName}`); 
            setNb(true); 
        }
        else if (!((userName === 'admin' || userName === 'operator' || userName === 'supervisor') && password === 'welcome')) {
            alert("Invalid Credentials")
            setPassword('')
            setUserName('')
            history.push(`/`)
        }
    }
    const checkIsAuth = () => {
        const _isAuth = localStorage.getItem('isAuth');
        const _user = localStorage.getItem('user');
        const _password = localStorage.getItem('password');
        if (_isAuth && _user && _password) history.push(`/${localStorage.getItem('user')}`)
    }
    useEffect(() => {
        checkIsAuth()
    }, [])
    return (
        <div>
            <Form>
                <Form.Group className="mb-3" controlId="formBasicEmail">
                    <Form.Label>Username</Form.Label>
                    <Form.Control type="text" placeholder="Enter Username" onChange={e => setUserName(e.target.value)}
                    />
                </Form.Group>
                <Form.Group className="mb-3" controlId="formBasicPassword">
                    <Form.Label>Password</Form.Label>
                    <Form.Control type="password" placeholder="Password" onChange={e => setPassword(e.target.value)} />
                </Form.Group>
                <Button variant="primary" onClick={submit}>
                    Submit
                </Button>
            </Form>
        </div>
    )
}

export default withRouter(Login)