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 bacause `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.
Advertisement
Answer
How about destructuring your auth context, since you are only using setUser inside useEffect?
const { setUser } = useAuth() useEffect(() => { .... }, [setUser])