I'm learned that React will re-render after state changed e.g. setState
from useState()
, calling the function or variable from useContext()
variable. But now I'm don't understand that why I get the ESLint
warning call the context function inside the useCallback()
without dependency in the list. If I put the dependency in the list, useCallback()
will be re-rendered and useEffect()
dependency from useCallback()
variable will do again. So how to fix the react-hooks/exhaustive-deps
when calling the function inside the useContext()
variable?
Auth.js
import React, { createContext, useContext, useEffect, useMemo, useState } from "react";
import * as AuthAPI from "../API/AuthAPI"
import Loading from "../Page/Loading"
const AuthContext = createContext()
export const AuthProvider = ({children}) => {
const [user,setUser] = useState()
const [loadingInitial,setLoadingInitial] = useState(true)
useEffect(()=>{
AuthAPI.getCurrentUser()
.then((user)=>setUser(user))
.catch((error)=>{console.log(error)})
.finally(()=>setLoadingInitial(false))
},[])
const login = async (email,password) => {
const user = await AuthAPI.login({email,password})
setUser(user)
return user
}
const register = async (firstname,lastname,email,password) => {
const user = await AuthAPI.register({firstname,lastname,email,password})
setUser(user)
return user
}
const logout = async () => {
const response = await AuthAPI.logout()
setUser(undefined)
}
const value = useMemo(()=>({
user,
setUser,
login,
register,
logout
}),[user])
return (
<AuthContext.Provider value={value}>
{loadingInitial ? <Loading/> : children}
</AuthContext.Provider>
)
}
export const useAuth = () => {
return useContext(AuthContext)
}
Logout.js
import { useCallback, useEffect, useState } from "react";
import { Navigate, useLocation, useNavigate } from "react-router-dom";
import { useAuth } from "../Hooks/Auth";
import * as AuthAPI from "../API/AuthAPI"
import Loading from "./Loading";
function Logout() {
const auth = useAuth()
const location = useLocation()
const navigate = useNavigate()
const [isLoggedOut,setIsLoggedOut] = useState(false)
const logout = useCallback(async () => {
console.log("Logging out!")
await AuthAPI.logout()
auth.setUser((prevState)=>(undefined))
setIsLoggedOut(true)
},[auth]) // --> re-rendered because `auth` context in re-rendered when set `user` state.
useEffect(()=>{
logout()
},[logout]) // --> this also to run again from `logout` callback is being re-rendered.
if (!isLoggedOut) {
return <Loading/>
}
return (
<Navigate to="/login" replace/>
)
}
export default Logout
Any help is appreciated.
How about destructuring your auth context, since you are only using setUser inside useEffect?
const { setUser } = useAuth()
useEffect(() => {
....
}, [setUser])