문제상황
개발환경
Next.js 13.4.2
TailwindCSS
next-themes 라이브러리를 활용
다크모드를 구현하려했다.
https://github.com/pacocoursey/next-themes
GitHub - pacocoursey/next-themes: Perfect Next.js dark mode in 2 lines of code. Support System preference and any other theme wi
Perfect Next.js dark mode in 2 lines of code. Support System preference and any other theme with no flashing - GitHub - pacocoursey/next-themes: Perfect Next.js dark mode in 2 lines of code. Suppor...
github.com
사용법이 다 나와있어서 설명문을 보고 그대로 적용하면 다 되는 줄 알았는데, 버튼이 대체 작동을 안 한다.
도대체 문제는 무엇인가. 아마 내가 잘못 적용했겠지.
버튼을 클릭 할 때 콘솔 로그를 찍어보니 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 컴포넌트 사용시, 컴포넌트 간의 구조에 대해서 이해하지 못한 것으로 발생한 문제이다.
공식문서를 보면 이에 대한 예시를 살펴 볼 수 있다.
Getting Started: React Essentials | Next.js
To build applications with Next.js, it helps to be familiar with React's newer features such as Server Components. This page will go through the differences between Server and Client Components, when to use them, and recommended patterns. If you're new to
nextjs.org
해법
이전 layout.js 코드는 다크 모드가 적용되려면 다크모드 버튼이 있는 Hedader 컴포넌트가 Providers(ThemeProvider) 컴포넌트 안에 감싸져 있어야 하는 것이다. 그래서 아래와 같이 다시 구성했다.
버튼은 이제 잘 작동한다. 이제 모드에 따라서 색상 전환 구성을 다르게 바꾸면 된다.
참고
https://www.patterns.dev/posts/provider-pattern
Provider Pattern
Make data available to multiple child components
www.patterns.dev
'개발 학습일지(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() (1) | 2023.03.27 |
댓글