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 }
}
CodePudding user response:
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> }