React 다크 모드 구현 – 반동 및 스타일 구성 요소로 쉽게

사이트에 접속하면 다크모드를 문제없이 사용할 수 있는 페이지를 볼 수 있다.
사실 쓰다보면 가끔 사용했는데 막상 구현하려고 하니 어떻게 구현해야할지 막막했습니다.
다크모드인지 여부에 대한 상태 정보는 상태를 할당하여 페이지를 담당하는 모든 컴포넌트에 전파하고 이에 따라 CSS를 변경해야 할 것 같습니다.

어떤 식으로든 CSS를 사용하여 웹사이트를 구축했다면 위의 프로세스가 결코 쉽지 않다는 것을 알고 있을 것입니다.

그리고 프로젝트가 상당히 크고 장난감 프로젝트가 아닌 경우 소품 드릴링을 경험할 수 있습니다.

상태 할당으로 인한 구현 문제

모호하게 뿌리를 둔 구성 요소에 isDark라는 상태를 할당한다고 가정합니다.
물론 다크모드나 라이트모드 토글버튼이 있을 것이고 토글버튼을 누르면 라이트모드나 다크모드로 상태가 바뀌게 됩니다.
컴포넌트 A에는 컴포넌트 B가 있고 컴포넌트 B에는 컴포넌트 C가 자식으로 있다고 가정하면 컴포넌트 A는 isDark 상태를 컴포넌트 B에 props로 전달해야 하며 컴포넌트 B에서도 동일한 프로세스를 수행해야 합니다.
isDark는 그것이 어두운 모드인지 여부를 전역적으로 알려야 하기 때문입니다.

하지만 프로젝트가 크다면 어떨까요? 100개 또는 200개의 부품을 배송해야 하는 경우에는 어떻게 합니까? 제공되지 않는 구성 요소를 주의 깊게 확인해야 하며 코드 재사용 가능성이 심각하게 제한됩니다.

구현 방법

모든 구성 요소의 상태에 액세스하기 위해 Facebook에서 만든 Recoil을 사용하여 상태 관리 라이브러리를 사용합니다.
또한 스타일이 지정된 구성 요소에서 제공하는 ThemeProvider를 사용하여 다크 모드 또는 라이트 모드 테마에 직접 액세스합니다.

npm install --save styled-components
npm install recoil

설계된 구성 요소를 설치하고 반격하려면 위 명령을 입력하십시오. 그리고 create-react-app으로 생성한 폴더 안의 src 폴더에 theme.js 파일을 생성하고 다음과 같이 입력합니다.
꼭 저처럼 하실 필요는 없습니다.

export const darkTheme = {
  textColor: "#dcdde1",
  backgroundColor: "#2f3640",
};

export const lightTheme = {
  textColor: "#353b48",
  background: "#fff",
};

각 테마에서 사용할 테마 이름과 색상을 작성한 후 내보냅니다.
이제 스타일이 지정된 구성 요소가 설정되었으므로 반동을 전역 변수로 설정하여 어두운 모드에 있는지 여부를 알 수 있습니다.

Recoil을 사용하려면 먼저 src 폴더에 atom.js를 생성하고 다음과 같이 작성합니다.

import { atom } from "recoil";

export const isDarkAtom = atom({
  key: "isDark",
  default: false,
});

Recoil에서 Atom을 가져온 후 atom() 내부의 객체 형식으로 키와 기본값을 설정합니다.
사이트 방문자에게 라이트 모드를 보여주기 위해 기본적으로 false를 기본값으로 설정했습니다.
그런 다음 앱 구성 요소로 돌아갑니다.

import { isDarkAtom } from "./atom";
...

const isDark = useRecoilValue(isDarkAtom);

컴포넌트에 다음 코드를 추가한 후:

import { ThemeProvider } from "styled-components";
import { useRecoilValue } from "recoil";
import { isDarkAtom } from "./atom";
import { darkTheme, lightTheme } from "./theme";
function App() {
  const isDark = useRecoilValue(isDarkAtom);
  return (
    <ThemeProvider theme={isDark ? darkTheme : lightTheme}>
      <div></div>;
    </ThemeProvider>
  );
}

export default App;

ThemeProvider에서 isDark가 true이면 이전에 설정한 darkTheme을 사용하고 그렇지 않으면 lightTheme을 사용합니다.
이 설정을 사용하면 상태가 전체적으로 변경될 때마다 CSS가 기본 색상으로 변경됩니다.