사고쳤어요
[React / ts] Book Store 만들기 - ③ ThemeSwitcher 만들기 본문
버튼을 클릭하여 라이트 테마 <-> 다크 테마를 변경할 수 있는 기능을 구현해보자.
// theme.ts
export type ThemeName = "light" | "dark";
type ColorKey = "primary" | "background" | "secondary" | "third";
interface Theme {
name: ThemeName;
color: Record<ColorKey, string>;
}
export const light: Theme = {
name: "light",
color: {
primary: "brown",
background: "lightgray",
secondary: "blue",
third: "green",
},
};
export const dark: Theme = {
name: "dark",
color: {
primary: "coral",
background: "midnightblue",
secondary: "darkblue",
third: "darkgreen",
},
};
export const getTheme = (themeName: ThemeName): Theme => {
switch (themeName) {
case "light":
return light;
case "dark":
return dark;
}
};
declare module "styled-components" {
export interface DefaultTheme extends Theme {}
}
먼저 theme.ts에서 라이트 테마와 다크 테마일 때 스타일을 작성해준다.
themeContext.tsx
import { createContext, ReactNode, useEffect, useState } from "react";
import { getTheme, ThemeName } from "../../style/theme";
import { ThemeProvider } from "styled-components";
import { GlobalStyle } from "../../style/global";
const DEFAULT_THEME_NAME = "light";
const THEME_LOCALSTORAGE_KEY = "book_store_theme";
interface State {
themeName: ThemeName;
toggleTheme: () => void;
}
export const state = {
themeName: DEFAULT_THEME_NAME as ThemeName,
toggleTheme: () => {},
};
export const ThemeContext = createContext<State>(state);
export const BookStoreThemeProvider = ({
children,
}: {
children: ReactNode;
}) => {
const [themeName, setThemeName] = useState<ThemeName>(DEFAULT_THEME_NAME);
const toggleTheme = () => {
setThemeName(themeName === "light" ? "dark" : "light");
localStorage.setItem(
THEME_LOCALSTORAGE_KEY,
themeName === "light" ? "dark" : "light"
);
};
useEffect(() => {
const savedThemeName = localStorage.getItem(
THEME_LOCALSTORAGE_KEY
) as ThemeName;
setThemeName(savedThemeName === "light" ? "dark" : "light");
}, []);
return (
<ThemeContext.Provider value={{ themeName, toggleTheme }}>
<ThemeProvider theme={getTheme(themeName)}>
<GlobalStyle themeName={themeName} />
{children}
</ThemeProvider>
</ThemeContext.Provider>
);
};
다음으로 themeContext.tsx에서 ThemeContext와 BookStoreThemeProvider를 정의해준다.
<ThemeContext.Provider>에 value로 themeName과 toggleName을 넣어주어 하위 컴포넌트들에서도 themeName과 toggleName을 사용할 수 있도록 설정해준다.
또한 테마 변경 시마다 localStorage에 해당 데이터를 저장하여 다시 웹페이지를 접속하더라도 스타일을 유지하도록 한다.
// ThemeSwitcher.tsx
import { useContext } from "react";
import { ThemeContext } from "../context/ThemeContext";
const ThemeSwitcher = () => {
const { themeName, toggleTheme } = useContext(ThemeContext);
return (
<button
onClick={() => {
toggleTheme();
}}
>
{themeName}
</button>
);
};
export default ThemeSwitcher;
마지막으로 toggleTheme을 사용할 버튼을 만들어준다.
이제 이 버튼을 누르면 toggleTheme()이 호출되어 themeName이 light, dark로 바뀌며 설정된다.
'웹 풀스택' 카테고리의 다른 글
[React / ts] Book Store 만들기 - ⑤ 라우터 만들기 (0) | 2025.04.21 |
---|---|
[React / ts] Book Store 만들기 - ④ 컴포넌트 제작과 테스트파일 만들기 (0) | 2025.04.20 |
[React / ts] Book Store 만들기 - ② 레이아웃 구성, 글로벌 스타일 적용 (0) | 2025.04.18 |
[React / ts] Book Store 만들기 - ① 프로젝트 생성과 폴더 구조 설정 (0) | 2025.04.17 |
[React / ts] Task App 만들기 - ⑦ Firebase 연동하여 로그인, 로그아웃 만들기 (0) | 2025.04.17 |