React-7 (23/03/03)

nazzzo·2023년 3월 5일
0

Styled-Component

1. React Project 설정


1. 관련 패키지 설치

npm init -y
npm install -D webpack webpack-cli @babel/core @babel/preset-env @babel/preset-react
npm install -D webpack-dev-server html-webpack-plugin babel-loader mini-css-extract-plugin



2. 웹팩 환경설정

  • webpack.config.js 설정
  • css-loader 설정
  • styled-components 이슈 해결 (process.ENV)
npm install process

[webpack.config.js]
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  name: "styled-components_v1",
  mode: "development",
  resolve: {
    extensions: [".js", ".jsx"],
  },
  entry: "./src/index.jsx",
  module: {
    rules: [
      {
        test: /\.jsx?/,
        loader: "babel-loader",
        // babelrc
        options: {
          presets: ["@babel/preset-env", "@babel/preset-react"],
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "index.html",
      filename: "index.html",
    }),
  ],
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
  },
  devServer: {
    static: {
      directory: path.join(__dirname, "dist"),
    },
    compress: true,
    port: 3001,
    hot: true,
    historyApiFallback: true,
  },
};



+) 간편 핫로딩을 위한 package.json 설정

  "scripts": {
    "dev" : "webpack server"
  },

3. 리액트 & 스타일드 컴포넌트 설치

npm install react react-dom styled-component



4. 기본 디렉토리 & 파일 생성

|-- src
|---- app.js
|---- index.jsx
|-- index.html

위 트리구조를 따라 파일을 생성합니다


[index.html]

<body>
    <div id="root"></div>
</body>

[./src/app.jsx]

import React from 'react';

const App = () => {
    return <>Hello world!</>
}

export default App

[./src/index.jsx]

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(<App></App>);



5. 웹팩 번들링 & 서버 실행

npx webpack
npx webpack server
npm run dev

(*위 명령어 각각이 어떻게 동작하는지 설명할 수 있어야 합니다)




2. Styled-Components




2-1. 스타일드 컴포넌트 설정

스타일드 컴포넌트를 다루기 전에 CSS-loader를 먼저 설정하도록 하겠습니다

  • style-loader : <head><style></style>
  • css-loader : <head><link href...>
npm install -D mini-css-extract-plugin css-loader styled-components

1. 웹팩 환결설정 수정


[webpack.config.js]

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');


module.exports = {
  name: "styled-components_v1",
  mode: "development",
  resolve: {
    extensions: [".js", ".jsx"],
  },
  entry: "./src/index.jsx",
  module: {
    rules: [
      {
        test: /\.jsx?/,
        loader: "babel-loader",
        // babelrc
        options: {
          presets: ["@babel/preset-env", "@babel/preset-react"],
        },
      },
      {
        test: /\.css/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "index.html",
      filename: "index.html",
    }),
    new MiniCssExtractPlugin({ filename: "bundle.css" })
  ],
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
  },
  devServer: {
    static: {
      directory: path.join(__dirname, "dist"),
    },
    compress: true,
    port: 3001,
    hot: true,
    historyApiFallback: true,
  },
};

2. 디렉토리 구조 수정

|-- /src
|---- /components
|----- button.jsx
|---- /pages
|----- main.jsx
|---- index.jsx
|---- app.jsx



  1. App 컴포넌트에서 main 컴포넌트를 불러옵니다
import React from "react";
import Main from "./pages/main";

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

export default App;

  1. ./pages/main.jsx, ./component/button.jsx

[main.jsx]

import React from "react";
import Button from "../components/button"

const Main = () => {
  return (
    <>
      <h1>Logo</h1>
      <ul>
        <li>Hello world</li>
        <li>
            <Button>
                <span>버튼1</span>
            </Button>
            <Button>
                <span>버튼1</span>
            </Button>
        </li>
        <li></li>
      </ul>
    </>
  );
};


export default Main

[button.jsx]

import React from 'react';

const StyledButton = ({ children }) => {
    return <button>{children}</button>
}

export default StyledButton
  • StyledButton으로 내보내고(export), Button으로 받았습니다(require)
    위와 같이 컴포넌트를 주고받을 때 변수명은 달라져도 상관없습니다

  • 컴포넌트의 innerHTML은 children으로 전달하는 것이 직관적입니다
    그리고 children에는 엘리먼트도 함께 포함시켜서 전달할 수 있습니다
    (<Button><span>버튼1</span></Button>에서 <span>도 children으로 전달)



2-2. 스타일드 컴포넌트 적용하기


[button.jsx]

import React from "react";
import styled, { css } from "styled-components";

const flexCenter = css`
    display: inline-flex;
    justify-content: center;
    align-items: center;
    outline: none;
    border: none;
`

const Button = styled.button`
    ${flexCenter}
    padding: 7px 14px;
    font-size: 11px;
    font-weight: bold;
`

const StyledButton = ({ children }) => {
  return <Button>{children}</Button>;
};

export default StyledButton;
  • 위와 같이 자주 사용하는 CSS 옵션은 변수로 따로 빼서 쓰는 것을 추천합니다
  • 반응형 웹을 고려해서 되도록 픽셀단위의 크기조정은 하지 않는 것이 좋아요



2-3. ThemeProvider


[App.js]

import React from "react";
import Main from "./pages/main";
import { ThemeProvider } from "styled-components";

const App = () => {
    const colorChip = {
        blue: '#228be6',
        gray: "#adb5db",
        pink: "#f06595",
    }

  return (
    <>
      <ThemeProvider theme={colorChip}>
        <Main></Main>
      </ThemeProvider>
    </>
  );
};

export default App;

최상위 컴포넌트에서 기본 컬러를 설정하고 하위 컴포넌트에 프롭스로 전달합니다
(전역 상태의 원리에 대해서는 추후에 Redux를 배우면서 파악하기로...)


[button.jsx]

import React from "react";
import styled, { css } from "styled-components";

const flexCenter = css`
  display: inline-flex;
  justify-content: center;
  align-items: center;
  outline: none;
  border: none;
`;

// 특정 props 값이 존재한다면 넓이 100% 부여하기
const fullWidthStyle = css`
  ${(props) => {
    return (
      props.fullWidth &&
      css`
        width: 100%;

        // 두 번째 버튼 간격을 벌리고 싶을 때
        & + & {
          margin-top: 10px;
        }

        & + & {
          margin-right: 10px;
        }
      `
    );
  }}
`;

const Button = styled.button`
  ${flexCenter}
  ${fullWidthStyle}
    padding: 7px 14px;
  font-size: 11px;
  font-weight: bold;

  // 기본 색상 설정
  /* background: ${(props) => {
    switch (props.color) {
      case "blue":
        return props.theme.blue;
      case "gray":
        return props.theme.gray;
      case "pink":
        return props.theme.pink;
    }
  }}; */
  background: ${(props) => props.theme[props.color]};

  color: #fff;

  // hover
  &:hover {
    background-color: #3399a4;
    cursor: pointer;
  }

  & span {
    color: #fff;
  }
`;

// 자바스크립트 객체의 중괄호와, JSX 문법을 쓰기 위한 중괄호를 구분할 수 있어야 돼요
const StyledButton = ({ children, ...rest }) => {
  return <Button {...rest}>{children}</Button>;
};

export default StyledButton;

0개의 댓글