728x90
몇 달 전, 바닐라JS에서 CSS로 다크모드 설정하는 방법을 공부했다.
그리고 리액트를 공부하다가 다시 한번 다크모드 설정을 구현하게 되었는데,
너모너모 쉬워서 깜짝 놀랐다.
잊고 싶지 않아서 글로 남겨본다.
1. 다크모드 Context 만들기
앱 전반적으로 활용해야하는 설정이라면 Context를 사용해서 구현하는 게 편리하다.
다크모드도 앱 전체에 적용되어야 하는 값이기 때문에 Context를 활용하여 구현해 준다.
// DarkModeContext.jsx
import { createContext, useContext, useEffect, useState } from 'react';
export const DarkModeContext = createContext();
export function DarkModeProvider({ children }) {
const [darkMode, setDarkMode] = useState(false);
// 토글 버튼을 활용해 다크모드를 변경할 수 있게 구현했다.
const toggleDarkMode = () => {
setDarkMode(!darkMode);
updateDarkMode(!darkMode);
};
// 다크모드 초기화
useEffect(() => {
// 로컬 스토리지에 다크모드 값이 있다면 그 값을 사용하고, 없는 경우 윈도우 설정을 따라간다.
const isDark =
localStorage.theme === 'dark' ||
(!('theme' in localStorage) &&
window.matchMedia('(prefers-color-scheme: dark)').matches);
setDarkMode(isDark);
updateDarkMode(isDark);
}, []);
return (
<DarkModeContext.Provider value={{ darkMode, toggleDarkMode }}>
{children}
</DarkModeContext.Provider>
);
}
// 다크모드 변경 함수
function updateDarkMode(darkMode) {
if (darkMode) {
document.documentElement.classList.add('dark'); // html 클래스에 'dark' 값을 추가한다.
localStorage.theme = 'dark';
} else {
document.documentElement.classList.remove('dark'); // html 클래스에 'dark' 값을 제거한다.
localStorage.theme = 'light';
}
}
// 내부적으로 useContext를 사용해서 다크모드 Context를 만들어주고, 외부에서는 신경쓰지 않도록 해준다.
export const useDarkMode = () => useContext(DarkModeContext);
2. 다크모드 Context 적용하기
구현한 Context를 앱에 적용해 준다.
사용법은 간단하다. DarkModeProvider로 감싸주면 된다.
이제 모든 자식 노드에서 다크모드 값에 접근할 수 있다.
//app.js
...
function App() {
const [filter, setFilter] = useState(filters[0]);
return (
<DarkModeProvider> // 여기!
<Header filters={filters} filter={filter} onFilterChange={setFilter} />
<TodoList filter={filter} />
</DarkModeProvider>
);
}
...
3. 다크모드 토글링 연결
다크모드를 토글링할 버튼에 다크모드 토글링 함수를 연결해 준다.
// Header.jsx
...
export default function Header({ filters, filter, onFilterChange }) {
const { darkMode, toggleDarkMode } = useDarkMode();
return (
<header className={styles.header}>
<button className={styles.darkModeButton} onClick={toggleDarkMode}> // 클릭 시 다크모드를 토글한다.
{darkMode ? <BsSunFill /> : <BsMoonFill />} // 다크모드인지 여부에 따라 아이콘을 다르게 보여준다.
</button>
</header>
);
}
4. 다크모드 스타일 연결
다크모드가 true
인 경우 html 클래스를 추가해서 다크모드를 설정할 수 있도록 구현했다.
이 클래스 값을 사용해서 style에 정의한 값을 변경해 준다.
// index.css
// 다크모드가 아닌 경우 사용하는 색상 값
:root{
--color-bg-dark: #f5f5f5;
--color-bg: #fdfffd;
--color-gray: #d1d1d1;
--color-text: #22243b;
--color-accent: #f16e03;
--color-white: white;
--color-scrollbar: #aaa7a7;
}
// 다크모드인 경우 사용하는 색상 값
html.dark {
--color-bg-dark: #1a1c35;
--color-bg: #22243b;
--color-gray: #707070;
--color-text: #f5f5f5;
}
반응형
'개발공부 > 웹' 카테고리의 다른 글
React Router 란? (0) | 2023.05.06 |
---|---|
React Immer로 상태관리하기 (0) | 2023.05.05 |
Reducer로 React에서 상태 관리 하는 방법 (0) | 2023.05.04 |
이벤트 델리게이션이란? (0) | 2023.02.14 |
HTML이 화면에 렌더링 되는 순서 (DOM? CSSOM?) (0) | 2023.02.14 |