[FE skill] useRouter 사용시 re-render 문제

손두희(SONDOOHEE)·2023년 4월 17일
0

데쉬보드 개발 중 layout으로 user Info, 알림, 로그아웃 기능의 Header 컴포넌트를 개발하였다.

Bug

데쉬보드에 content를 이동시키는 Side bar가 있는데
이를 통해 content, 즉 route가 발생하면 Header를 다시 렌더링한다.

Solution

useMemo를 통해 login시 한번만 render 할수 있도록 구현, 대신 알림의 내용이 바뀌면 다시 render가 되야한다.

Problem during debugging

컴포넌트에 useRouter을 사용하는데 이를 불러올때마다 강제로 렌더링 시키는 것 같다.

이를 해결하기 위해서 생각한 방법들...
1. useRouter를 컴포넌트에서 새롭게 지정하는게 아니라 부모 컴포넌트에서 지정하고 props로 내린다.
2. useCallback을 사용해서 useRouter()를 한번만 호출할 수 있도록 해본다.
3. useRouter를 상수값으로 지정해서 전역변수에 저장하고 필요할 때 마다 꺼내서 사용한다.

1번 방법 결과
Main.tsx

const Main: React.FC<MainProps> = ({ children }) => {
const router = useRouter()
return (
...
{useMemo(()=><Header router={router}/>,[])}
...
)

export default Main;

Header.tsx

const Header: React.FC<HeaderProps> =({router}) => {
...
const handleLogout =() => {
    LocalStorage.removeItem(ACCESS_TOKEN);
    LocalStorage.removeItem(REFRESH_TOKEN);
    router.push("/login");
  };
return (
...
)
}

export default Header;

props 로 넘기니 따로 useRouter를 계속 불러오지 않고 Header render도 초기에만 일으키고 content가 바뀌어도 re-render가 발생하지 않는다.
대신!! 이렇게 props 로 넘기는 코드가 굳이 이렇게 까지 props 로 내려야할까 하는 고민이 생겼다.

2번 방법 결과
Header.tsx

const Header: React.FC<HeaderProps> =({router}) => {
...
const router =  useRouter();

const handleLogout =useCallback(() => {
  LocalStorage.removeItem(ACCESS_TOKEN);
  LocalStorage.removeItem(REFRESH_TOKEN);
  router.push("/login");
},[]);
return (
...
)
}

handleLogout 함수를 useCallback 을 사용해서 한번만 호출하도록 하였다.
근데 const router 에서 useRouter() 를 계속 호출해서인지
content 가 바뀌면 다시 useRouter()를 발생시켜 render가 된다.

3번 방법 결과

import { useRouter } from "next/router";
import { create } from "zustand";

const useHeadStore = create(()=> ({
  router: ()=>{
    const router = useRouter()
    return router
  }
}));

export default useHeadStore

로 useRouter 를 zustand 전역변수 함수로 지정했다.
하지만

Unhandled Runtime Error
Error: 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.

다음과 같은 에러가 나왔고
hooks를 지정하는 곳이 잘못된거 같다...

Result

일단 프로젝트를 진행시켜야 하니 1번 방법으로 진행을 시키고
자문을 받아 다른 방법이 있는지 확인을 받아봐야겠다

profile
작업을 기록하는 개발자

0개의 댓글