React에서 다크 모드 전환
먼저 기본 레이아웃을 만들었습니다. 다음으로 dark 및 light 색 구성표를 조합했습니다. 약간의 시행착오가 필요했지만 sufficient contrast에 대한 모든 조합을 테스트하고 배치를 실험한 후 6개의 CSS 변수가 필요하다는 것을 알았습니다. 변수 이름이 어두운 테마의 컨텍스트에서 의미가 있기 때문에 "어두운 우선"개발을 사용했다고 말할 수 있습니다. 밝은 테마는 변형이 적지만 필요합니다
--button-border
. 여기서 --accent
는 배경과 같은 색상이 됩니다..theme-dark {
--dark-text: #292929;
--light-text: #F9F8F8;
--dark-background: #2F4550;
--light-background: #586F7C;
--accent: #B8DBD9;
--button-border: #B8DBD9;
}
.theme-light {
--dark-text: #5E4B56;
--light-text: #5E4B56;
--dark-background: #DBE7E4;
--light-background: #EDDCD2;
--accent: #DBE7E4;
--button-border: #5E4B56;
}
그런 다음 기본 레이아웃에 색상을 적용하기 시작했습니다.
html, #root {
background-color: var(--dark-background);
color: var(--dark-text);
}
nav {
background-color: var(--dark-background);
color: var(--light-text);
}
.main-container {
background-color: var(--light-background);
}
팝하고 싶은 콘텐츠 섹션의 배경도
--accent
로 설정했습니다. --dark-text
는 어두운 테마의 모든 배경에서 작업했을텐데 섹션 제목을 --light-text
로 설정하여 더 눈에 띄게 했습니다.Musthaq Ahamad'sbasic theme switcher tutorial를 찾았고 이를 기능적인 React 구성 요소에 적용하기 시작했습니다.
테마를 변경하고 테마 기본 설정에 대한 localStorage를 확인하는 기능을
themes.js
라는 파일에 넣었습니다.function setTheme(themeName) {
localStorage.setItem('theme', themeName);
document.documentElement.className = themeName;
}
function keepTheme() {
if (localStorage.getItem('theme')) {
if (localStorage.getItem('theme') === 'theme-dark') {
setTheme('theme-dark');
} else if (localStorage.getItem('theme') === 'theme-light') {
setTheme('theme-light')
}
} else {
setTheme('theme-dark')
}
}
module.exports = {
setTheme,
keepTheme
}
내
App.js
파일에서 내 keepTheme()
에 useEffect()
를 추가했습니다.import { keepTheme } from './utils/themes';
function App() {
useEffect(() => {
keepTheme();
})
}
다음으로 내 탐색 모음 구성 요소에 토글 구성 요소를 추가했습니다. Chris Bongers’ Tutorial 을 기반으로 Katia De Juan’s Dribbble 토글 스타일을 지정했습니다. 그럼 나adjusted the size and flipped it to default to dark mode . 이 토글이 너무 귀여워서 죽을 수도 있지만 이 튜토리얼은 모든
<button>
또는 클릭 가능한 <input>
에서 작동합니다. 먼저 기본 JSX, 로컬 상태 및 localStorage에서 가져온 테마를 저장할 변수를 설정합니다.import React, { useEffect, useState } from 'react';
import '../styles/toggle.css';
import { setTheme } from '../utils/themes';
function Toggle() {
const [togClass, setTogClass] = useState('dark');
let theme = localStorage.getItem('theme');
return (
<div className="container--toggle">
<input type="checkbox" id="toggle" className="toggle--checkbox" onClick={handleOnClick} />
<label htmlFor="toggle" className="toggle--label">
<span className="toggle--label-background"></span>
</label>
</div>
)
}
export default Toggle;
사용자가 토글을 클릭하면 페이지의 테마가 변경되고 토글이 함께 변경되기를 원합니다. 로컬 상태에서 가져온
setTheme()
함수와 setTogClass()
를 handleOnClick 함수에 추가했습니다. 위의 JSX에서 토글의 클릭 가능한 부분으로 전달되는 위치를 볼 수 있습니다.const handleOnClick = () => {
if (localStorage.getItem('theme') === 'theme-dark') {
setTheme('theme-light');
setTogClass('light')
} else {
setTheme('theme-dark');
setTogClass('dark')
}
}
이 구성 요소
useEffect()
를 사용하여 로컬 상태 togClass가 항상 올바른 테마로 로드되는지 확인했습니다.useEffect(() => {
if (localStorage.getItem('theme') === 'theme-dark') {
setTogClass('dark')
} else if (localStorage.getItem('theme') === 'theme-light') {
setTogClass('light')
}
}, [theme])
내 토글이 확인란이기 때문에 어두운 테마는 선택되지 않은(달) 상태를 표시하고 밝은 테마는 선택(태양) 상태를 표시해야 합니다.
defaultChecked
이 원하는 대로 작동하지 않아 체크되지 않은 <input>
를 다음 조건부 렌더링(조건부 연산자)으로 대체했습니다.{
togClass === "light" ?
<input type="checkbox" id="toggle" className="toggle--checkbox" onClick={handleOnClick} checked />
:
<input type="checkbox" id="toggle" className="toggle--checkbox" onClick={handleOnClick} />
}
<button>
를 사용한 경우 이와 같은 조건부 렌더링을 사용하여 <button>
태그 내에서 className 속성을 변경하고 동일한 효과를 얻을 수 있습니다.토글 구성 요소의 코드는 다음과 같습니다.
import React, { useEffect, useState } from 'react';
import '../styles/toggle.css';
import { setTheme } from '../utils/themes';
function Toggle() {
const [togClass, setTogClass] = useState('dark');
let theme = localStorage.getItem('theme');
const handleOnClick = () => {
if (localStorage.getItem('theme') === 'theme-dark') {
setTheme('theme-light');
setTogClass('light')
} else {
setTheme('theme-dark');
setTogClass('dark')
}
}
useEffect(() => {
if (localStorage.getItem('theme') === 'theme-dark') {
setTogClass('dark')
} else if (localStorage.getItem('theme') === 'theme-light') {
setTogClass('light')
}
}, [theme])
return (
<div className="container--toggle">
{
togClass === "light" ?
<input type="checkbox" id="toggle" className="toggle--checkbox" onClick={handleOnClick} checked />
:
<input type="checkbox" id="toggle" className="toggle--checkbox" onClick={handleOnClick} />
}
<label htmlFor="toggle" className="toggle--label">
<span className="toggle--label-background"></span>
</label>
</div>
)
}
업데이트
이 구성 요소의 논리를 리팩토링하고 액세스 가능하게 만든 방법을 보려면 .
마지막으로 제가 가장 좋아하는 부분은 SVG 색상 전환입니다! CSS 변수는 SVG 코드에서도 작동합니다!
DEVICON 에서 Github 및 Chrome 아이콘에 대한 SVG 코드를 받았습니다. Github 아이콘의 경우
<g>
에서 하나의 채우기 속성만 변경해야 했습니다.<g fill="var(--dark-text)">
Chrome 아이콘에는
<circle>
및 <path>
에 채우기 속성이 있습니다.<circle fill="var(--dark-text)" cx="63.624" cy="64.474" r="22.634"></circle><path fill="var(--dark-text)" ...>
결과는 다음과 같습니다.
결론
관련 코드를 모두 포함하려고 했지만 Github repository 에서 내 사이트의 전체 코드를 볼 수도 있습니다. 이 글이 마음에 드셨거나 질문이 있으시면 댓글을 남겨주세요! 또한 이 튜토리얼에 따라 구축된 모든 것을 보고 싶습니다.
Reference
이 문제에 관하여(React에서 다크 모드 전환), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/abbeyperini/toggle-dark-mode-in-react-28c9텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)