[fastcampus] Ch.5 React Component Styling (1)

productuidev·2022년 3월 8일
0

React Study

목록 보기
8/52
post-thumbnail
post-custom-banner

패스트캠퍼스 한 번에 끝내는 프론트엔드 개발(Online) 강의 정리


Ch.5 React Component Styling (1)

1. Style Loaders

npx create-react-app style-loaders-example

npm run eject : Webpack 설정 꺼내서 변경

webpack.config.js

// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;

//CRA에서 4가지 다른 방식으로 스타일 파일들을 가져다 해석하여 사용함을 알 수 있음

CSS (webpack.config.js)

import './App.css';

// cssRegex
{
  test: cssRegex,
  exclude: cssModuleRegex,
  use: getStyleLoaders({
    importLoaders: 1,
    sourceMap: isEnvProduction
    ? shouldUseSourceMap
    : isEnvDevelopment,
  }),
  sideEffects: true,
},

CSS Module (webpack.config.js)

import styles from './App.module.css';

// cssModuleRegex
{
  test: cssModuleRegex,
  use: getStyleLoaders({
    importLoaders: 1,
    sourceMap: isEnvProduction
    ? shouldUseSourceMap
    : isEnvDevelopment,
    modules: {
      getLocalIdent: getCSSModuleLocalIdent,
    },
  }),
},

Sass (Webpack.config.js)

import './App.scss';
import './App.sass';

// sassRegex
{
  test: sassRegex,
  exclude: sassModuleRegex,
  use: getStyleLoaders({
    importLoaders: 1,
    sourceMap: isEnvProduction
    ? shouldUseSourceMap
    : isEnvDevelopment,
  },
    'sass-loader'
  ),
  sideEffects: true,
},

Sass Module (webpack.config.js)

import styles from './App.module.scss';
import styles from './App.module.sass';

// sassModuleRegex
{
  test: sassModuleRegex,
  use: getStyleLoaders({
    importLoaders: 1,
    sourceMap: isEnvProduction
    ? shouldUseSourceMap
    : isEnvDevelopment,
    modules: {
      getLocalIdent: getCSSModuleLocalIdent,
    },
  }
    'sass-loader'
  ),
},

2. CSS/SASS

// App.js
import './App.css'; // 전역적으로 추가됨

src/App.js

src/App.css

css 파일을 import할 때 주의해야 하는 것은 스타일을 주려고 하는 클래스의 이름들이
전역적으로 오염되지 않게 하는 것이 중요함. (기계적으로 자동화되는 부분이 아니어서
팀 내부적으로 규칙을 정하고 그 규칙에 맞게 클래스를 쓰는 방법론이 생기기 시작)

.App
.App-header (.App .header)
.App-logo (.App .logo)
.App-link (.App .link)

BEM 방법론 (Block, Element, Modifier)

3. CSS Module/SASS Module

import styles from "./App.module.css";

function App() {
  return (
    <div className={stlyes["App"]}>
      <header className={styles["header"]}>
        <img src={logo} className={styles["logo"]} alt="logo" />
      </header>
      <a className={styles["link"]}>link</a>
    </div>
  );
}
  • styles은 객체

CRA에서 CSS modlue을 사용하는 경우

CSS Modules allows the scoping of CSS by automatically creating a unique classname of the format [filename]\_[classname]\_\_[hash].

모듈 : 전역적으로 오염되지 않게 사용한다

className="App"
className={stlyes["App"]}

Button 컴포넌트

src/components/Button.jsx

import styles from "./Button.module.css";

const Button = (props) =>
<button className={styles["button"]}
{...props} />;

export default Button;
import React from "react";
import styles from "./Button.module.css";

class Button extends React.Component {
  state = { loading: false };

  render() {
    return (<button
    onClick={this.startLoading}
    className={this.state.loading ? `${styles["button"]}` `${styles["loading"]}`
      : styles["button"]
    }
    {...this.props} />
    );
  }

  startLoading = () => {
    this.setState( { loading: true, });
    setTimeout( () => {
      this.setState({ loading: false, });
    }, 1000);
  };
}

src/components/Button.module.css

.button { background:transparent; border-radius:3px; border:2px solid red; color:red; margin:0 1em; padding:0.25em 1em; font-size:20px; }
.loading { border:2px solid grey; color:grey; }

src/App.js

import styles from "./App.module.css";
import Button from "./components/Button"; // 추가

function App() {
  return (
    <div className={stlyes["App"]}>
      <header className={styles["header"]}>
        <img src={logo} className={styles["logo"]} alt="logo" />
      </header>
      // <a className={styles["link"]}>link</a>
      <Button>Button</Button>
    </div>
  );
}

className을 쉽게 쓰도록 도와주는 라이브러리

npm i classnames

src/App.js

import React from "react";
import styles from "./Button.module.css";

class Button extends React.Component {
  state = { loading: false };

  render() {
    console.log(classNames("foo", "bar")); // test
    console.log(classNames("foo", "bar", "baz")); // test

    console.log(classNames( {foo:true}, {bar:false} )); // test
    console.log(classNames(null, false, "bar", undefined, 0, 1, {baz:null}, "" )); // falsy한 값은 안 나옴

    console.log(classNames(styles["button"], styles["loading"] )); // 실제 클래스값

    return (<button
    onClick={this.startLoading}
    className={this.state.loading ? `${styles["button"]}` `${styles["loading"]}`
      : styles["button"]
    }
    {...this.props} />
    );
  }

  startLoading = () => {
    this.setState( { loading: true, });
    setTimeout( () => {
      this.setState({ loading: false, });
    }, 1000);
  };
}

src/App.js

import React from "react";
import styles from "./Button.module.css";

class Button extends React.Component {
  state = { loading: false };

  render() {
    return (<button
    onClick={this.startLoading}
    className={classNames(styles["button"], // classNames로 변경하기
      loading: this.state.loading,
    )}
    {...this.props} />
    );
  }

  startLoading = () => {
    this.setState( { loading: true, });
    setTimeout( () => {
      this.setState({ loading: false, });
    }, 1000);
  };
}

https://github.com/JedWatson/classnames

Alternate bind version (for css-modules)

var classNames = require('classnames/bind');

var styles = {
  foo: 'abc',
  bar: 'def',
  baz: 'xyz'
};

var cx = classNames.bind(styles);

var className = cx('foo', ['bar'], { baz: true }); // => "abc def xyz"

classnames/bind 적용하기

src/App.js

import React from "react";
import styles from "./Button.module.css";
import classNames from 'classnames/bind'; // 추가

const cx = classNames.bind(styles) // module.css에서 가져온 styles 객체 넣기

console.log( cx('button', 'loading') )

class Button extends React.Component {
  state = { loading: false };

  render() {

    const {loading} = this.state; // {loading} 정의

    return (<button
    onClick={this.startLoading}
    className={cx('button', { loading } )} // 변경
    {...this.props} />
    );
  }

  startLoading = () => {
    this.setState( { loading: true, });
    setTimeout( () => {
      this.setState({ loading: false, });
    }, 1000);
  };
}

Sass/Scss > CSS로 컴파일한 것이기 때문에 동일한 방식으로 작업


이어서.

profile
필요한 내용을 공부하고 저장합니다.
post-custom-banner

0개의 댓글