📌 상황
프로젝트에서 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
https://reactrouter.com/en/main/start/concepts
'React' 카테고리의 다른 글
[React] UNSAFE_componentWillMount 경고 해결: react-helmet-async 사용 (0) | 2024.09.30 |
---|---|
[React] lazy 와 Suspense 이용해서 컴포넌트 동적으로 로딩하기 (0) | 2024.09.23 |
[React] Alias 설정으로 코드 가독성 높이기 (0) | 2024.09.19 |
[React] React Router로 페이지 이동하기 (1) | 2024.09.12 |
[React] 컴포넌트와 props (1) | 2024.09.11 |