Search code examples
reactjsauthenticationauthorizationmernlogout

Handling user context on logout for user.isAdmin in ReactJs / Uncaught TypeError: user is null


I am trying to build a functionality in ReacJs (MERN) app, for my navbar link to '/admin', to be only visible when user.isAdmin === true.

So my navbar (just an excerpt) looks the follwing:

Navbar

import { useAuthContext } from '../hooks/useAuthContext'
import { useIsAdmin } from '../hooks/useAdmin'

const Navbar = () => {
    const [nav, setNav] = useState(false)
    const {logout} = useLogout()
    const {user} = useAuthContext()
    const isAdmin = useIsAdmin()

//and on return
{ isAdmin ? <Link to='/admin'><li className='p-4 hover:text-[#00df9a] transition-all duration-500'>Admin {user.name}</li></Link> : <div></div> }

I as well made a function to get the user.isAdmin from AuthContext

useAdmin

import { useEffect, useState } from 'react';
import { useAuthContext} from '../hooks/useAuthContext';

export function useIsAdmin() {
    const { user } = useAuthContext();
    const [isAdmin, setIsAdmin] = useState(null);
  
    useEffect(() => {
      if (user) {
        setIsAdmin(user.isAdmin && user);
      }
    }, [user]);
  
    useEffect(() => {
      if (!user || user === null) {
        setIsAdmin(null);
      }
    }, [user]);
  
    return isAdmin;
  }

And this works okay, normal user does not see the /admin link, and user.isAdmin does.

However, the problem starts when I try to logout the user.isAdmin, then I receive "Uncaught TypeError: user is null" as user changes back to Object { user: null }. On contrary, I do not have that error, if I log out regular user, although it comes back to Object { user: null } as well.

I have tried working on my hook/function with no result, but I am guessing there is some problem with my authContext and global context for user.

So for reference my authContext file and logout.

Any hints and tips would be much appreciated.

AuthContext


import { createContext, useReducer, useEffect } from 'react'

export const AuthContext = createContext()

export const authReducer = (state, action) => {
  

  switch (action.type) {
    case 'LOGIN':
      return { user: action.payload }
    case 'LOGOUT':
      
      window.localStorage.clear()
      return {user: null}

    case 'DELETE_USER':
      return {...state, user: state.user.filter(u =>
         u.id !== action.payload
      )}    
    default:
      return state
  }
}

export const AuthContextProvider = ({ children }) => {
  const [state, dispatch] = useReducer(authReducer, {
  user: null
})

  useEffect(() => {
    const user = JSON.parse(localStorage.getItem('user'))

    if (user) {
      dispatch({ type: 'LOGIN', payload: user }) 
    }

  }, [])

  console.log('AuthContext state:', state)

  return (
    <AuthContext.Provider value={{ ...state, dispatch }}>
      { children }
    </AuthContext.Provider>
  )
}

useLogout

import { useAuthContext } from './useAuthContext'

export const useLogout = () => {
    const { dispatch } = useAuthContext()
  
    const logout = () => {
      // remove user from local storage
      localStorage.removeItem('user')
  
      // dispatch logout action
      dispatch({ type: 'LOGOUT' })
    }
  
    return { logout }
  }

Solution

  • Well, i forgot to add user to my if check in navbar. After this change, all works like a charm.

    Navbar

     { isAdmin && user ? <Link to='/admin'><li className='p-4 hover:text-[#00df9a] transition-all duration-500'>Admin {user.name}</li></Link> : <div></div> }