잿꽃's posting Garden

REACT styled-components 'ThemeProvider'를 이용한 darkmode만들기 본문

WEB/REACT

REACT styled-components 'ThemeProvider'를 이용한 darkmode만들기

잿꽃 2022. 4. 25. 10:26

REACT styled-components의 'ThemeProvider'를 이용한 darkmode만들어 보겠습니다.

 

 

 

 

[기초단계]

1. styled-components를 이용할 것이므로 설치한다.

터미널에서 yarn을 이용해 설치한다.

yarn add styled-components

 

2. scr폴더 내에 Components파일 1개와 css 객체를 담당할 일반 js파일을 만든다.

컴포넌트는 앞글자 대문자

 

3. Components파일 내에 rsc + tab, enter를 하여 함수형 컴포넌트를 만는다.

 

4. app.js에 만든 Components를 연결한다.

import React from 'react';
import Darkmode from './Darkmode';

const App = () => {
  return (
    <div>
      <Darkmode>
      </Darkmode>
    </div>
  );
};

export default App;

 

5. 'yarn start'를 터미널에 입력하여 렌더링되는지 확인한다.

 

 

 

[실행단계]

1. Darkmode.js에 내용을 간단히 작성한다.

import React from 'react';

const Darkmode = () => {
    return (
        <div>
            <div>
            <h1>잿꽃</h1>
            <button>lightmode</button>
            <button>darkmode</button>
            </div>
            <p>시간</p>
            <p>시간</p>
        </div>
    );
};

export default Darkmode;

 

2. css의 객체를 담을 theme.js에 내용을 작성한다.

export const lightmodeTheme = {
    headerBgColor : "#333",
    headerTextColor : "#fff",
    contentBgColor : "#fff",
    contentTextColor : "#333"
}

export const darkmodeTheme = {
    headerBgColor : "#fff",
    headerTextColor : "#333",
    contentBgColor : "#333",
    contentTextColor : "#fff"
}

 

3. app.js에 ThemeProvider와 theme.js파일을 연결한다.

(Darkmode도 연결해준다.)

ThemeProvider는 styled-components에서 제공하는 것으로 theme이라는 값을 제공하고 props로 전달이 가능하다.

import React, { useState } from 'react';
import Darkmode from './Darkmode';
import { ThemeProvider } from 'styled-components';
import { lightmodeTheme, darkmodeTheme } from './theme';

const App = () => {
  return (
    <ThemeProvider>
      <Darkmode>
      </Darkmode>
    </ThemeProvider>
  );
};

export default App;

ThemeProvider에 따라 theme.js 파일 내 lightmodeTheme 또는 darkmodeTheme이 번갈아 가면서 활성화가 되어야 한다. 번갈아 활성화 될 수 있게 변수를 만들 것이며 이 값은 변하기 때문에 useState()를 이용하여 만들 것이다.

 

4. app.js에 ThemeProvider의 theme값을 변화시키기 위한 변수만들기

import React, { useState } from 'react';
import Darkmode from './Darkmode';
import { ThemeProvider } from 'styled-components';
import { lightmodeTheme, darkmodeTheme } from './theme';

const App = () => {
  const [isDark, setIsDark] = useState(false);
  return (
    <ThemeProvider theme={isDark? darkmodeTheme : lightmodeTheme}>
      <Darkmode>
      </Darkmode>
    </ThemeProvider>
  );
};

export default App;

setIsDark를 이용하여 isDark의 값을 변경시킬 것이다. 이것을 Darkmode 컴포넌트에서 해야하므로 Darkmode에 인자가 필요하다. Darkmode에 인자를 만들어서 app.js에서 Darkmode의 인자에 isDark와 setIsDark값을 넣어줄 것이다.

 

5. Darkmode.js에서 props를 지정하고 styled-components를 이용해 내용물을 꾸며준다.

Darkmode에 인자를 추가해준다.

app.js에서 <Darkmode isDark={변수} setIsDark={변수}>이렇게 사용할 수 있을 것이다.

import React from 'react';
import styled from 'styled-components';

// darkmode에 인자 추가
const Darkmode = ({isDark, setIsDark}) => {
    return (
        <TotalWrapper>
            <HeaderWrapper>
            <h1>잿꽃</h1>
            <button>lightmode</button>
            <button>darkmode</button>
            </HeaderWrapper>
            <ContentsTime1>시간</ContentsTime1>
            <ContentsTime2>시간</ContentsTime2>
        </TotalWrapper>
    );
};

//styled-components로 꾸미기
const TotalWrapper = styled.div`
    width: 100%;
    height: 100vh;
`;
const HeaderWrapper = styled.header`
    width: 100%;
    height: 100px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 20px;
`;
const ContentsTime1 = styled.div`
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 3rem;
    margin: 100px 0 50px;
`
const ContentsTime2 = styled.div`
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 4rem;
`

export default Darkmode;

 

6. styled-components로 꾸민 요소에 props로 app.js theme과 연결하기

props를 이용하여 app.js theme에서 lightmodeTheme과 darkmodeTheme 중 해당되는 객체의 key값을 사용할 수 있다.

import React from 'react';
import styled from 'styled-components';

// darkmode에 인자 추가
const Darkmode = ({isDark, setIsDark}) => {
    return (
        <TotalWrapper>
            <HeaderWrapper>
            <h1>잿꽃</h1>
            <button>lightmode</button>
            <button>darkmode</button>
            </HeaderWrapper>
            <ContentsTime1>시간</ContentsTime1>
            <ContentsTime2>시간</ContentsTime2>
        </TotalWrapper>
    );
};

//styled-components로 꾸미기
const TotalWrapper = styled.div`
    width: 100%;
    height: 100vh;
    /*  props 전달 
        app.js에서 theme요소가 바뀌므로 해당 내용의 key를 가져온다.
        ex) app.js에서 ThemeProvider theme = {lightmodeTheme}일 경우
        lightTheme.headerBgColor
    */
    background-color: ${(props)=> props.theme.contentBgColor};
    color : ${(props) => props.theme.contentTextColor};
`;
const HeaderWrapper = styled.header`
    width: 100%;
    height: 100px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 20px;
    background-color: ${(props)=> props.theme.headerBgColor};
    color : ${(props) => props.theme.headerTextColor};
`;
const ContentsTime1 = styled.div`
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 3rem;
    margin: 100px 0 50px;
`
const ContentsTime2 = styled.div`
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 4rem;
`

export default Darkmode;

 

7. button과 Darkmode의 인자와 연결하기

isDark에 의해 두 개의 버튼 중에 하나만 활성화 되어야 하므로 isDark의 값에 따라 한 개의 버튼만 나타난다.

const Darkmode = ({isDark, setIsDark}) => {
    return (
        <TotalWrapper>
            <HeaderWrapper>
            <h1>잿꽃</h1>
            {isDark? <button>lightmode</button> : <button>darkmode</button>} 
            </HeaderWrapper>
            <ContentsTime1>시간</ContentsTime1>
            <ContentsTime2>시간</ContentsTime2>
        </TotalWrapper>
    );
};

버튼을 누르면 isDark의 값이 바뀌면서 다음 버튼이 나타나야 한다.

const Darkmode = ({isDark, setIsDark}) => {
    const change = ()=>{
        setIsDark(!isDark)
    }
    return (
        <TotalWrapper>
            <HeaderWrapper>
            <h1>잿꽃</h1>
            {isDark? <button onClick={change}>lightmode</button> : <button onClick={change}>darkmode</button>} 
            </HeaderWrapper>
            <ContentsTime1>시간</ContentsTime1>
            <ContentsTime2>시간</ContentsTime2>
        </TotalWrapper>
    );
};

app.js에 Darkmode의 인자를 전달하지 않았기 때문에 작동하지는 않는다.

 

8. app.js에서 Darkmode의 인자와 변수를 연결하기

import React, { useState } from 'react';
import Darkmode from './Darkmode';
import { ThemeProvider } from 'styled-components';
import { lightmodeTheme, darkmodeTheme } from './theme';

const App = () => {
  const [isDark, setIsDark] = useState(false);
  return (
    <ThemeProvider theme={isDark? darkmodeTheme : lightmodeTheme}>
      <Darkmode isDark={isDark} setIsDark={setIsDark}>
      </Darkmode>
    </ThemeProvider>
  );
};

export default App;

이제 버튼이 잘 잘동하게 된다.

 

 

 

[결과화면]

추가적으로 꾸며보았다.

 

 

[추가적으로 꾸민 코드 더보기 클릭]

더보기

추가 된 내용 2가지

상단의 버튼을 리액트 아이콘으로 꾸몄다.

시간이라고 쓰인 부분을 실제 시간을 넣는다.

 

 

 

상단의 버튼을 리액트 아이콘으로 꾸미는 방법

1. 터미널에서 react-icons를 설치한다.

yarn add styled-components react-icons

 

2. *참고자료에서 찾은 아이콘을 Darkmode.js에 import한다.

import { MdDarkMode, MdOutlineDarkMode } from 'react-icons/md';

 

3. 기존의 button을 styled-components으로 꾸며준다.

시멘틱태그가 아니므로 styled(이름)``;으로 작성한다.

const DarkBtn = styled(MdDarkMode)`
    cursor: pointer;
    font-size: 30px;
    color : ${(props) => props.theme.headerTextColor};
`;
const LightBtn = styled(MdOutlineDarkMode)`
    cursor: pointer;
    font-size: 30px;
    color : ${(props) => props.theme.headerTextColor};
`;

 

 

 

시간이라고 쓰인 부분에 실제 시간을 넣는 방법

1. Darkmode.js에서 return위에 아래의 코드를 추가한다.

//시간 변화를 반영할 useState()사용
    //현재 시간을 가져올 수 있는 new Date() 내장객체 이용
    const [time, setTime] = useState(new Date());
    
    //문서가 마운트 되면 1회 실행 useEffect(()=>{}, [])
    //시간을 1초마다 반환 setInterval(()=>{} ,1000)
    //새로운 시간을 setTime에 넣어서 time값 변화
    useEffect(()=>{
        setInterval(()=>{
            setTime(new Date())
        }, 1000)
    }, [])

 

2. Darkmode.js에서 <ContentsTime1>시간</ContentsTime1>부분의 '시간'을 수정한다.

사용자의 문화권에 맞는 시간표기법으로 객체의 시간을 리턴하는 함수이다.

자세한 내용은 하단 *참고자료에서 확인

<ContentsTime1>{time.toLocaleDateString()}</ContentsTime1>
<ContentsTime2>{time.toLocaleTimeString()}</ContentsTime2>

 

 

전체 Darkmode.js 코드

import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import { MdDarkMode, MdOutlineDarkMode } from 'react-icons/md';

// darkmode에 인자 추가
const Darkmode = ({isDark, setIsDark}) => {
    const change = ()=>{
        setIsDark(!isDark)
    }

    //시간 변화를 반영할 useState()사용
    //현재 시간을 가져올 수 있는 new Date() 내장객체 이용
    const [time, setTime] = useState(new Date());
    
    //문서가 마운트 되면 1회 실행 useEffect(()=>{}, [])
    //시간을 1초마다 반환 setInterval(()=>{} ,1000)
    //새로운 시간을 setTime에 넣어서 time값 변화
    useEffect(()=>{
        setInterval(()=>{
            setTime(new Date())
        }, 1000)
    }, [])

    return (
        <TotalWrapper>
            <HeaderWrapper>
            <h1>잿꽃</h1>
            {isDark? <DarkBtn onClick={change}>lightmode</DarkBtn> : <LightBtn onClick={change}>darkmode</LightBtn>
            } 
            </HeaderWrapper>
            <ContentsTime1>{time.toLocaleDateString()}</ContentsTime1>
            <ContentsTime2>{time.toLocaleTimeString()}</ContentsTime2>
        </TotalWrapper>
    );
};

//styled-components로 꾸미기
const TotalWrapper = styled.div`
    width: 100%;
    height: 100vh;
    /*  props 전달 
        app.js에서 theme요소가 바뀌므로 해당 내용의 key를 가져온다.
        ex) app.js에서 ThemeProvider theme = {lightmodeTheme}일 경우
        lightTheme.headerBgColor
    */
    background-color: ${(props)=> props.theme.contentBgColor};
    color : ${(props) => props.theme.contentTextColor};
`;
const HeaderWrapper = styled.header`
    width: 100%;
    height: 100px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 20px;
    background-color: ${(props)=> props.theme.headerBgColor};
    color : ${(props) => props.theme.headerTextColor};
`;
const ContentsTime1 = styled.div`
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 3rem;
    margin: 100px 0 50px;
`;
const ContentsTime2 = styled.div`
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 4rem;
`;

const DarkBtn = styled(MdDarkMode)`
    cursor: pointer;
    font-size: 30px;
    color : ${(props) => props.theme.headerTextColor};
`;
const LightBtn = styled(MdOutlineDarkMode)`
    cursor: pointer;
    font-size: 30px;
    color : ${(props) => props.theme.headerTextColor};
`;

export default Darkmode;

 

 

 

참고자료

React Icons (react-icons.github.io)

 

React Icons

React Icons Include popular icons in your React projects easily with react-icons, which utilizes ES6 imports that allows you to include only the icons that your project is using. Installation (for standard modern project) npm install react-icons --save Usa

react-icons.github.io

toLocaleDateString - 생활코딩 (opentutorials.org)

 

toLocaleDateString - 생활코딩

요약(Summary) 사용자의 문화권에 맞는 시간표기법으로 객체의 시간을 리턴 문법(Syntax) toLocaleDateString() 인자(Parameters) 없음 반환값(Return) string, 운영체제에 설정된 문화권에 맞는 형태로 시간을 표

opentutorials.org

 

useContext를 이용한 darkmode만들기

https://flowerofashes.tistory.com/37

 

REACT useContext을 이용한 darkmode 만들기

REACT useContext를 이용하여 props을 전역 변수로 만들어서 darkmode를 만들어보자 [기초단계] 1. styled-components를 이용할 것이므로 설치한다.  터미널에서 yarn을 이용하여 설치한다. yarn add styled-comp..

flowerofashes.tistory.com

 

728x90

'WEB > REACT' 카테고리의 다른 글

REACT Todolist 만들기 - 2  (0) 2022.04.29
REACT Todolist 만들기 - 1  (0) 2022.04.28
REACT useContext을 이용한 darkmode 만들기  (0) 2022.04.24
REACT HOOK의 용도 정리  (0) 2022.04.23
REACT 'ToDoList'를 만들기 위한 기초 연습  (0) 2022.04.21
Comments