React

[React] useLocation() 오류: Router 내부에서만 사용 가능해요

방혜진 2024. 9. 26. 21:16

📌 상황

프로젝트에서 Zustand 를 이용해 다크모드 기능을 구현하던 중, 현재 경로 정보를 가져오기 위해 useLocation() 훅을 사용하려고 했는데 다음과 같은 에러 메시지를 접하게 됐다.

Uncaught Error: useLocation() may be used only in the context of a <Router> component

 


🔍 문제 분석

번역을 해보니 "useLocation() 은 <Router> 컴포넌트의 컨텍스트에서만 사용될 수 있습니다." 라는 의미였다.

관련 문서를 찾아보니, 이 문제는 useLocation() 훅이 Router 컴포넌트의 자식으로 존재하지 않을 때 발생하는 오류였다.

 

나는 RouterProvider 를 사용해서 라우터를 관리하고 있었고, 아래와 같이 ThemeSwitcher 컴포넌트에서 useLocation() 훅을 호출하고 있었다. 저 부분이 문제가 됐던 것이다.

<>
  <RouterProvider router={router} />
  <ThemeSwitcher />  // 이곳에서 useLocation() 사용
</>

useLocation() 은 현재 URL 의 정보를 반환하는 훅인데, 이 훅을 사용하기 위해서는 반드시 Router 의 컨텍스트 안에서 호출되어야 한다.

만약 Router 없이 useLocation() 훅을 호출하면, 경로 정보를 찾을 수 없기 때문에 위와 같은 에러가 발생하게 되는 것이다.

 


⚒️ 해결 방법

단순히 useLocation() 을 사용하고 있는 컴포넌트를 Router 내부로 옮기는 방법으로 문제를 해결했다.

// router.jsx

{
    path: '/',
    element: (
      <Layout>
        <Suspense fallback={<Loading />}>
          <Outlet />
        </Suspense>
      </Layout>
    ),
    children: [...home, ...guestbook],
    errorElement: <NotFound />
  },
// Layout.jsx

const Layout = ({ children }) => {
  return (
    <div>
      <ThemeSwitcher />

      {/* 헤더 */}
      <Header />

      <div className="max-w-screen-xl w-full mx-auto">
        <div className="flex flex-col md:flex-row xl:ml-10 xl:mr-4 lg:mx-auto lg:ml-8 md:ml-6">
          {/* 사이드바 */}
          <SideBar />
          <main className="flex-1">{children}</main>
        </div>
      </div>

      {/* 푸터 */}
      <Footer />
    </div>
  );
};

라우터 구조에서 Layout 부분으로 옮겨주었고, 이렇게 하니 useLocation() 이 정상적으로 동작했다.

 


❓ 왜 Router 내부로 옮겨줘야 할까?

useLocation 훅은 React Router 의 컨텍스트에 의존하기 때문이다. Router 는 현재 경로와 관련된 정보를 제공하는 최상위 컴포넌트로, 이 컴포넌트가 없으면 useLocation() 은 경로 정보를 가져올 수 있는 환경을 갖추지 못하게 된다.

 

결국, useLocation() 을 사용할 때는 해당 컴포넌트가 반드시 Router 의 자식으로 존재해야 URL 정보를 제대로 사용할 수 있게 된다.

 

 

📝 결론

이번 문제는 useLocation() 을 사용할 때, 그 훅이 Router 내부에서만 작동해야 한다는 사실을 간과해서 발생한 오류였다.

React Router 훅을 사용할 때는 항상 해당 컴포넌트가 Router 의 자식으로 위치하고 있는지 확인할 것 !!!!!

 


💡 참고 문헌

https://ko.legacy.reactjs.org/docs/context.html

 

Context – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

https://reactrouter.com/en/main/start/concepts

 

Main Concepts | React Router

 

reactrouter.com