Lun
Lun

Reputation: 1131

react component detect changes only after a refresh

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!

Upvotes: 0

Views: 150

Answers (1)

Badal Saibo
Badal Saibo

Reputation: 3665

  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'))
    })
    */
...
}

Upvotes: 1

Related Questions