0

Navbar.js

import React from 'react'
import { useHistory } from 'react-router'
import { useEffect } from 'react'
import { useState } from 'react'

const Navbar = () => {
    let history = useHistory()
    let [token, setToken] = useState('')

    const logout = () => {
        setToken(window.localStorage.removeItem('token'))
        history.push('/login')
    }
    
    useEffect(() => {
        setToken(window.localStorage.getItem('token'))
    })

    return (
        <nav>
            <div className='nav-content'>
                <h1>LunCare <i class="fas fa-plus"></i></h1>   

                {
                token !== null ?
                <ul>
                    <li>
                        <a href='' onClick={logout}>Logout</a>
                    </li>
                </ul> 
                :
                <ul>
                    <li>
                        <a href='/register'>Register</a>
                        <a href='/login'>Login</a>
                    </li>
                </ul> 
                }
            </div>
        </nav>
    )
}

export default Navbar

Login.js (I dont think this is needed but ill include it)

import React from 'react'
import { useHistory } from 'react-router'

const Login = () => {
    let user = {
        username: '',
        password: ''
    }

    let error = false

    let history = useHistory()
    
    const login = (e) => {
        e.preventDefault()
        fetch('http://127.0.0.1:8000/auth/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(user)
      }).then(res => {
          if(res.status === 200 || res.status === 201) {
                return res.json()
          } else {
                error = true
          }
      })
        .then(data => {
    
        window.localStorage.setItem('token', data.token);
        history.push('/')
      })
        .catch(err => {

        })
      
    }
    
    const updateForm = (e) => {
        e.preventDefault()
        user[e.target.name] = e.target.value
    }

    return (
        <div className='form-container'>
            <form onSubmit={login}>
                <div className='form-content'>
                    <h1>Log In</h1>
                    <label>Name</label>
                    <input type='text' name='username' onChange={updateForm}></input>
                    <label>Password</label>
                    <input type='password' name='password' onChange={updateForm}></input>
                    <button type='submit'>Log In</button>
                </div>
            </form>
        </div>
    )
}

export default Login

Everything works as intended, but when I successfully login the navbar doesnt change accordingly... I need to refresh it so that it detects the token, how can I make it so that the navbar changes when the user gets redirected after logging in, any help is appreciated!

1
  • useEffect(() => { setToken(window.localStorage.getItem('token')) }) Pretty sure that you are doing an infinite rerender inside here. set it to useEffect(() => { setToken(window.localStorage.getItem('token')) }, []). The , [] part will make sure you only fetch the token once. Are you unmouning the navbar on logout? Commented Jul 19, 2021 at 12:57

1 Answer 1

1
  1. Move the token to a common parent component say Parent that renders, Nav and Login.
  2. Inside Parent should you declare the state, token.
  3. Pass the setter token function to Login, use that on your login handler function
// Login.js
...
const Login = ({ setToken }) => { // destructure `setToken`
   const login = (e) => {
        ...
        .then(data => {
    
        window.localStorage.setItem('token', data.token);
        setToken(data.token); // set the token here
        history.push('/')
      })
        .catch(err => {

        })
      ...
    }
}
  1. Pass both token and setToken to your Nav component
const Navbar = ({ token, setToken }) => { // destructure token and setToken here
...
    // let [token, setToken] = useState('')  // don't need this

    const logout = () => {
        window.localStorage.removeItem('token')
        setToken(null) // need to clear state after logging out
        history.push('/login')
    }
    
    /* Don't need this either
    useEffect(() => {
        setToken(window.localStorage.getItem('token'))
    })
    */
...
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.