본문 바로가기

Style

React - 컴포넌트에 스타일 입히기

인라인 스타일

const style = {
    backgroundColor: 'pink'
}

function Button({children, onClick}){
    return <button onClick={onClick} style={style}>
        {children}
    </button>;
}
function Button({children, onClick}){
    return <button onClick={onClick} style={{bckgroundColor: 'yellow'}}>
        {children}
    </button>;
}
  • 스타일의 속성값은 객체로 입력해야한다.
  • 객체의 key에 '-'가 들어있는 이름은 전부 카멜케이스로 바꿔 적어주어야한다.
  • 스타일 객체를 따로 빼지 않고, 위 예제중 2번째 코드처럼 직접 적어도 되지만 권장되지 않는다.

css 파일 import

//index.css
body{
    background-color: #191f2c;
    color: #fff;
}

// index.js
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(<App />);
  • css파일을 import할 때에는, 변수이름 없이, from키워드 없이 바로 경로를 작성한다.

클래스를 사용한 스타일

// Button.css
.Button{
    padding: 14px 27px;
    border-radius: 30px;
    outline: none;
    cursor: pointer;
    font-size: 17px;
}

.Button.blue{
background-color: rgba(0,89, 255, 0.2);
border: solid 1px #7090ff;
color: #7090ff;
}

.Button.red{
background-color: rgba(255,78, 78, 0.2);
border: solid 1px #ff4664;
color: #ff4664;
}

// Button.js
import './Button.css'

function Button({children, onClick, color = 'blue'}){
    const classNames = `Button ${color}`;
    return <button onClick={onClick} className={classNames}>
        {children}
    </button>;
}

export default Button;

위 코드를 보면, css파일에는 클래스명을 기준으로 스타일을 작성했고, jsx에서 className을 준 것을 알 수 있다.

className을 여러개 주려면 여러 클래스명 사이에 공백을 구분자로 넣어주어야함을 알 수 있다.

 

tip)

스타일 css속성중에 요소 바깥의 스타일(예를 들면 margin)에 영향을 주는 속성들은, 외부에서 정리하는 것이 좋다.

무슨 뜻이냐면, Button컴포넌트를 2개 가지고있는 app.js코드가 있을 때,

// App.js
import { useState } from 'react';
import Dice from "./Dice";
import Button from "./Buttom";

function App(){
    const [num, setNum] = useState(1);
    const handleRollClick = () => {
        setNum(3);
    }
    return (
        <div>
            <div>
                <Button onClick={handleRollClick}>던지기</Button>
                <Button>처음부터</Button>
            </div>
            <Dice color="red" num={num}/>
        </div>
    );
}
export default App;

Button컴포넌트들의 margin에대한 스타일은 Button컴포넌트에서 할 것이 아니라, App.js에서 정리하는 것이 좋다는 이야기이다.

Button 내부의 스타일은 Button.css에서, 많은 Button 컴포넌트들 사이의 margin은 외부에서 관리하는 것이 코드의 이해도도 높아지고 유지보수 관점에서도 좋다.


Create React App

사실 css파일을 불러오거나, 이미지파일을 불러오는 기능은 React 고유의 기능이 아니다.

Create Reat App 프로그램이 대신 설정해준 기능이다.

 

이미지를 불러올 때에는, 먼저 import를 해 둔 후, src에 해당 경로의 변수를 넣어주면 된다.

import diceImg from './assets/dice.png';

function Dice() {
  return <img src={diceImg} alt="주사위 이미지" />;
}

export default App;

아래와 같이 backgroundImage를 넣는 경우에도 import를 먼저 해주어야한다.

import HandIcon from './HandIcon';
import backgroundImg from './assets/purple.svg';
const style = {
  width: '166px',
  height: '166px',
  border: 'none',
  outline: 'none',
  textAlign: 'center',
  cursor: 'pointer',
  backgroundColor: 'transparent',
  backgroundImage: `url('${backgroundImg}')`,
  backgroundRepeat: 'no-repeat',
  backgroundPosition: 'center',
  backgroundSize: 'contain',
}

function HandButton({ value, onClick }) {
  const handleClick = () => onClick(value);
  return (
    <button style={style} onClick={handleClick}>
      <HandIcon value={value} />
    </button>
  );
}

export default HandButton;

위의 코드에서는, 변수를 자바스크립트에서 가져다 쓰는 것 이므로 템플릿 문자열 안에 ${} 로 변수를 집어넣었다.


Class Name을 여러개 줘야하는 경우

1. 템플릿 문자열을 사용하면

function Button({ isPending, color, size, invert, children }) {
  const classNames = `Button ${isPending ? 'pending' : ''} ${color} ${size} ${invert ? 'invert' : ''}`;
  return <button className={classNames}>{children}</button>;
}

export default Button;

 

2. 배열을 사용하면

function Button({ isPending, color, size, invert, children }) {
  const classNames = [
    'Button',
    isPending ? 'pending' : '',
    color,
    size,
    invert ? 'invert' : '',
  ].join(' ');
  return <button className={classNames}>{children}</button>;
}

export default Button;

위와같이 class name들을 배열로 만들어 놓은 후, join메서드를 사용해 문자열로 합칠 수 있다.

 

3. classnames 라이브러리를 사용하면

import classNames from 'classnames';

function Button({ isPending, color, size, invert, children }) {
  return (
    <button
      className={classNames(
        'Button',
        isPending && 'pending',
        color,
        size,
        invert && 'invert',
      )}>
     { children }
   </button >
  );
}

export default Button;

classnames 라이브러리는 설치가 필요하다.

npm install classnames

내가볼땐 이것도 그렇게 보기좋은것 같지는 않다. className을 많이 쓰지 않는 편이 가장 좋은걸까??