๐ŸŽจ ํ”„๋ก ํŠธ์—”๋“œ/React

[styled-components] ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ styled-components ๋‹คํฌ๋ชจ๋“œ/๋ผ์ดํŠธ๋ชจ๋“œ ์„ค์ •ํ•˜๊ธฐ

rigood 2023. 5. 18. 13:05

0. ์„ค์น˜

// styled-components ์„ค์น˜
npm i styled-components
npm i -D @types/styled-components

// ์ƒํƒœ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” recoil ์„ค์น˜
npm i recoil

 

1. ํƒ€์ž… ์„ ์–ธ

1) src ํด๋” ๋‚ด์— styled.d.ts ํŒŒ์ผ ์ƒ์„ฑํ•œ๋‹ค.

2) ์ƒ๋‹จ์— styled-components๋ฅผ importํ•œ๋‹ค.

3) styled-components ๋ชจ๋“ˆ์„ ์„ ์–ธํ•˜๊ณ , DefaultTheme ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์„ค์ •ํ•ด์ค€๋‹ค.

// styled.d.ts

import "styled-components";

declare module "styled-components" {
  export interface DefaultTheme {
    bgColor: string;
    boardColor: string;
    titleColor: string;
    cardColor: string;
    textColor: string;
  }
}

 

2. ํ…Œ๋งˆ ์ž‘์„ฑ

1) src ํด๋” ๋‚ด์— theme.ts ํŒŒ์ผ ์ƒ์„ฑํ•œ๋‹ค.

2) ์ƒ๋‹จ์— styled-components๋กœ๋ถ€ํ„ฐ DefaultTheme์„ importํ•œ๋‹ค.

3) ๋‹คํฌํ…Œ๋งˆ, ๋ผ์ดํŠธํ…Œ๋งˆ๋ฅผ ์„ ์–ธํ•˜๊ณ , importํ•œ DefaultTheme์„ ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•ด์ค€๋‹ค.

4) ๋‹คํฌ๋ชจ๋“œ, ๋ผ์ดํŠธ๋ชจ๋“œ์— ์‚ฌ์šฉ๋  ์ƒ‰์ƒ์„ ์ง€์ •ํ•ด์ค€๋‹ค.

// theme.ts

import { DefaultTheme } from "styled-components";

export const darkTheme: DefaultTheme = {
  bgColor: "#F2F1ED",
  boardColor: "#FFFDF6",
  titleColor: "#4C4A4B",
  cardColor: "#ffffff",
  textColor: "#000000",
};

export const lightTheme: DefaultTheme = {
  bgColor: "#F2F1ED",
  boardColor: "#FFFDF6",
  titleColor: "#4C4A4B",
  cardColor: "#ffffff",
  textColor: "#000000",
};

 

3. recoil๋กœ ๋‹คํฌ๋ชจ๋“œ state ๊ด€๋ฆฌ

1) index.tsx ํŒŒ์ผ์— RecoilRoot๋ฅผ ์…‹ํŒ…ํ•œ๋‹ค.

// index.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import { RecoilRoot } from 'recoil';
import App from './App';


const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <RecoilRoot>
      <App />
    </RecoilRoot>
  </React.StrictMode>
);

 

2) src ํด๋” ๋‚ด์— recoil.ts ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ , ๋‹คํฌ๋ชจ๋“œ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” atom์„ ์ƒ์„ฑํ•œ๋‹ค.

// recoil.ts

import { atom } from "recoil";

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

 

4. ThemeProvider ์…‹ํŒ…

1) App.tsx ํŒŒ์ผ์— styled-components์˜ ThemeProvider๋ฅผ ์…‹ํŒ…ํ•ด์ค€๋‹ค.

2) recoil์˜  useRecoilValue ํ›…์„ ํ†ตํ•ด isDarkAtom์„ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.

3) isDark๊ฐ€ true์ผ ๋•Œ๋Š” darkTheme์„, false์ผ ๋•Œ๋Š” lightTheme์„ ์ ์šฉํ•ด์ค€๋‹ค.

// App.tsx

import { ThemeProvider, createGlobalStyle } from 'styled-components';
import reset from "styled-reset";
import { useRecoilValue } from "recoil";
import { isDarkAtom } from './recoil';
import { darkTheme, lightTheme } from "./theme";
import Kanban from './Kanban';

const GlobalStyle = createGlobalStyle`
${reset};

*{
  box-sizing: border-box;
}
`;

function App() {
  const isDark = useRecoilValue(isDarkAtom);
  return (
    <ThemeProvider theme={isDark ? darkTheme : lightTheme}>
      <GlobalStyle />
      <Kanban />
    </ThemeProvider>
  )
}

export default App;

 

5. ์ปดํฌ๋„ŒํŠธ์—์„œ CSS ์„ค์ •ํ•˜๊ธฐ

styled-components์˜ props๋ฅผ ํ†ตํ•ด CSS๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

props.theme ์•ˆ์— defaultTheme์—์„œ ์„ค์ •ํ–ˆ๋˜ ๋ณ€์ˆ˜๋“ค์ด ์ž๋™์™„์„ฑ๋˜์–ด ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

// Kanban.tsx

import styled from "styled-components";

function Kanban() {
    return (
        <Layout>Kanban</Layout>
    )
}

export default Kanban

const Layout = styled.div`
color: ${props => props.theme.textColor}
`;