본문 바로가기
Issue🚨

Hook 사용 규칙 위반

by ZZiwon Choi 2024. 10. 4.

recoil로 토큰 관리를 하고 useRecoilState를 사용했는데 다음과 같은 오류가 발생했다. 

 

Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

 

찾아보니 Hook 규칙을 위반했을때 발생하는 오류였다. 

 

Hook을 많이 사용하지만 Hook 규칙에 대해서는 정확히 모르고 있었다...?😱

React 공식 문서에서 Hook의 규칙에 대해 살펴봤다. 

 

1. 최상위(at the Top Level)에서만 Hook을 호출해야 한다. 

반복문, 조건문 혹은 중첩된 함수 내에서 Hook을 호출하면 안된다. 대시 early return이 실행되기 전에 항상 React 함수의 최상위에서 Hook을 호출해야 한다. 

2. 오직 React 함수 내에서 Hook을 호출해야 한다. 

Hook을 일반적인 JavaScript 함수에서 호출하면 안된다. React 함수 컴포넌트에서 Hook을 호출해야된다. 

 

내가 위반한 규칙은 2번이었다. 

apiClient.interceptors.response.use(
    (res)=>{
        return res
    },
    async (err)=>{
        const originalRequest=err.config;

        if(err.response.status===401&& !originalRequest._retry){
            originalRequest._retry=true;
            try{
            	const refresh=useRecoilState(refreshToken);
                const newAccessToken=await refreshAccessToken(refresh);
                if(newAccessToken){
                    originalRequest.headers['access']=`Bearer ${newAccessToken}`;
                    return apiClient(originalRequest)
                }
            }catch(err:any){
                console.log("리프레시 토큰 재발급 실패:", err.message);
                console.log(err)
                if(originalRequest.navigation){
                    await goToLogin(originalRequest.navigation)
                }else{
                    console.log("네비게이션 객체가 없습니다.")
                }
            }
        }
        return Promise.reject(err)
    }
)

컴포넌트 함수가 아닌 axios 요청 인터셉터에서 useRecoilState를 호출해서 오류가 나는 것이었다. 

try{

    const refresh=useRecoilState(refreshToken); ❌

}

 

const ApiSet = () => {
    const [accessToken, setAccessToken] = useRecoilState(accessTokenState);
    const [refreshToken, setRefreshToken] = useRecoilState(refreshTokenState);

    request(apiClient);
    response(apiClient, setAccessToken, setRefreshToken);
}

 

=> 해당 훅은 밑에 컴포넌트 함수를 따로 만들어 호출하고, 위 코드도 함수로 만들어서 컴포넌트 함수에서 호출하는 방식으로 코드를 수정하였다. 

 

'Issue🚨' 카테고리의 다른 글

xcode에서 실수로 파일 삭제 했을때  (0) 2024.07.09