문제상황
개발환경
Next.js 13.4.2
TailwindCSS
next-themes 라이브러리를 활용
다크모드를 구현하려했다.
https://github.com/pacocoursey/next-themes
사용법이 다 나와있어서 설명문을 보고 그대로 적용하면 다 되는 줄 알았는데, 버튼이 대체 작동을 안 한다.
도대체 문제는 무엇인가. 아마 내가 잘못 적용했겠지.
버튼을 클릭 할 때 콘솔 로그를 찍어보니 theme에 저장된 값이 undefined로 나온다.
TailwindCSS의 문제인가
버튼 코드의 문제인가
localStorage의 문제인가
내 컴퓨터의 문제인가? 다른 사람이 구현한 코드는 또 잘 작동한다. 혼자 끙끙대길 수 시간 째.
// layout.js
export default async function RootLayout({ children }) {
let session = await getServerSession(authOptions);
return (
<html suppressHydrationWarning>
<body>
<Header />
<Providers>{children}</Providers>
<Footer />
</body>
</html>
);
}
//providers.js
"use client";
import { ThemeProvider } from "next-themes";
export function Providers({ children }) {
return (
<ThemeProvider attribute="class">
{children}
</ThemeProvider>
)
}
//DarkModeBtn.js
"use client";
import { useTheme } from "next-themes";
export default function DarkModeBtn() {
const { theme, setTheme } = useTheme();
return (
<>
<button
className="
inline-flex items-center
border-0 py-1 px-3 rounded text-base mt-4 md:mt-0
focus:outline-none
bg-gray-100
hover:bg-gray-50
hover:text-orange-500
dark:bg-slate-600
dark:text-slate-400
dark:hover:bg-slate-700
dark:hover:text-yellow-300
"
type="button"
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
>
{/* 라이트 모드 */}
<svg
xmlns="http://www.w3.org/2000/svg"
className="visible dark:invisible dark:h-0 dark:w-0 h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
clipRule="evenodd"
/>
</svg>
{/* 다크모드 */}
<svg
xmlns="http://www.w3.org/2000/svg"
className="visible dark:visible dark:h-5 dark:w-5 h-0 w-0"
viewBox="0 0 20 20"
fill="currentColor"
>
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
</svg>
</button>
</>
);
}
문제 원인 분석 및 알게 된점
다크모드 버튼은 기존에 Header 컴포넌트 내에서 구현되어 있는데,
혹시나 해서 다크모드 버튼을 layouts.js에서 provider 컴포넌트 안에 넣어서 작동해보니, 잘 작동하고 있었다.
-> 즉, 버튼 위치에 따라 작동 유무가 갈리는 것으로 보아 구현된 버튼에는 문제가 없는 것이다!
위 layout.js 에 대한 코드블럭 중에서 Header 컴포넌트 적용이 잘못되어 있던 것이다.
provider 컴포넌트 사용시, 컴포넌트 간의 구조에 대해서 이해하지 못한 것으로 발생한 문제이다.
공식문서를 보면 이에 대한 예시를 살펴 볼 수 있다.
해법
이전 layout.js 코드는 다크 모드가 적용되려면 다크모드 버튼이 있는 Hedader 컴포넌트가 Providers(ThemeProvider) 컴포넌트 안에 감싸져 있어야 하는 것이다. 그래서 아래와 같이 다시 구성했다.
버튼은 이제 잘 작동한다. 이제 모드에 따라서 색상 전환 구성을 다르게 바꾸면 된다.
참고
https://www.patterns.dev/posts/provider-pattern
'개발 학습일지(TIL)' 카테고리의 다른 글
TIL : Next.js localStorage를 활용한 배너, 하루 동안 닫기 구현 (0) | 2023.06.08 |
---|---|
TIL : next.js 커스텀 404 not-found 찾을 수 없는 페이지 구조 재설정 (0) | 2023.05.31 |
TIL : Next.js, useState와 useEffect 이용하여 댓글 실시간 업데이트 (0) | 2023.05.12 |
TIL : 트러블슈팅, NestJS 인터셉터 사용으로 리팩토링 (유저 로그인 정보에 따른 버튼 처리) (0) | 2023.03.31 |
TIL : typeORM 외래키 없이 조인. getRawMany() vs getMany() (0) | 2023.03.27 |
댓글