[TIL] React styled-components

대빵·2023년 11월 7일

오늘부터 React숙련주차가 시작되었닷..ㅎㅎ

이번주 React의 심화된 내용을 더 알아보고 공부하는 시간을 갖기 위해 첫번째 Styled Components의 대해서 정리를 해봅니다.

CSS-in-Js란?

단어 그대로 자바스크립트 코드로 CSS 코드를 작성하여 컴포넌트를 꾸미는 방식입니다.

순수한 CSS코드를 우리가 아니라, 자바스크립트를 이용해서 CSS코드를 만들 수 있습니다.

CSS-in-JS 방식을 사용하기 위해 우리는 새로운 패키지를 사용하는 것 입니다.

styled-components란?


styled-components는 우리가 리액트에서 CSS-in-JS 방식으로 컴포넌트를 꾸밀수 있게 도와주는 패키지 입니다.

styled-components외에도 다양한 패키지가 있지만, styled-components 예전부터 꾸준히 많은 개발자들에게 선택받은 패키지입니다.

패키지란,
React에는 없는 기능이지만 우리가 추가로 가져와서 사용할 수 있는 써드파티 프로그램

패키지들은 누군가에 의해 만들어진 것으로 npm에 모여 있다.
우리는 사용하고자 하는 패키지를 npm install 또는 yarn add 를 통해서 설치해서 사용할 수 있어, 앞으로 이렇게 React에서 자체적으로 제공하지 않지만, 사용하면 우리가 개발하는데 더 유용합니다.

styled-components 준비

VScode 플러그인 설치

styled-components를 이용해서 코드를 작성할 때 조금 더 편하게 하기위해 플러그인을 설치해야만 styled-components 안에서 스타일 코드를 편하게 작성할 수 있습니다.

yarn 에서 styled-components 설치

yarn add styled-components

vscode 터미널에서 명령을 입력해서 패키지를 설치를 해야 사용이 가능하다.

styled-components 사용

기본적인 사용법

import React from "react";
// styled-components에서 styled 라는 키워드를 import 합니다.
import styled from "styled-components";

// styled키워드를 사용해서 styled-components 방식대로 컴포넌트를 만듭니다. 
const StBox = styled.div`
	// 그리고 이 안에 스타일 코드를 작성합니다. 스타일 코드는 우리가 알고 있는 css와 동일합니다.
  width: 100px;
  height: 100px;
  border: 1px solid red;
  margin: 20px;
`;

const App = () => {
	// 그리고 우리가 만든 styled-components를 JSX에서 html 태그를 사용하듯이 사용합니다.
  return <StBox>박스</StBox>;
};

export default App;

가장 핵심이 되는 코드는 const StBox = styled.div``; 이 부분입니다.

styled. 뒤에는 html의 태그가 와서, 내가 원하는 html 태그를 사용해서 styled-components를 만들 수 있습니다.

div ➡️ styled.div
span ➡️ styled.span
button ➡️ styled.button

조건부 스타일링이란?

classname을 사용해서 구현하기는 조금 까다로운 조건부 스타일링을 styled-components를 이용하면 간편하게 할 수 있습니다.

만약에 스타일 코드를 작성할 때 if문을 사용할 수 있다면? , switch문을 사용할 수 있다면? , 삼항연산자를 사용할 수 있다면? 이라는 생각을 혹시 해보셨다면? CSS-in-JS 방식의 강점이 바로 스타일 코드를 JS코드 작성하듯이 스타일 코드를 작성할 수 있다는 점 입니다.

조건부 스타일링 구현

// src/App.js

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

// 1. styled-components를 만들었습니다.
const StBox = styled.div`
  width: 100px;
  height: 100px;
  border: 1px solid ${(props) => props.borderColor}; // 4.부모 컴포넌트에서 보낸 props를 받아 사용합니다. 
  margin: 20px;
`;

const App = () => {
  return (
    <div>
			{/* 2. 그리고 위에서 만든 styled-components를 사용했습니다. */}
			{/* 3. 그리고 props를 통해 borderColor라는 값을 전달했습니다. */}
      <StBox borderColor="red">빨간 박스</StBox>
      <StBox borderColor="green">초록 박스</StBox>
      <StBox borderColor="blue">파랑 박스</StBox>
    </div>
  );
};

export default App;

업로드중..

  1. styled-component를 생성
const StBox = styled.div``;
  1. styled-component를 부모 컴포넌트에서 사용
const App = () => {
  return (
    <div>
      <StBox>빨간 박스</StBox>
      <StBox>초록 박스</StBox>
      <StBox>파랑 박스</StBox>
    </div>
  );
};
  1. StBox 에 전달 (borderColor를 props로 자식컴포넌트, 여기서는 자식컴포넌트가 styled-components입니다.)
const App = () => {
  return (
    <div>
      <StBox borderColor="red">빨간 박스</StBox>
      <StBox borderColor="green">초록 박스</StBox>
      <StBox borderColor="blue">파랑 박스</StBox>
    </div>
  );
};
    1. 부모 컴포넌트에서 props를 보냈습니다. 자식 컴포넌트에서는 받아야겠죠? 아래와 같은 모양으로 받습니다. 순서대로 어떻게 된건지 알아봅시다.

      const StBox = styled.div`
        border: 1px solid ${(props) => props.borderColor};
      `;

    1) 첫째, 먼저 자바스크립트 코드를 사용하기 위해 ${ } 를 열어줍니다. 템플릿 리터럴

    2) 둘째, 비어있는 화살표 함수를 열어 줍니다. ${( )=>{ }}

    3) 셋째, 함수의 인자에서 props를 받아오고, props안에는 부모 컴포넌트에서 보낸 borderColor가 있습니다. 그것을 return 하면 ${(props)⇒{ return props.borderColor }} 이렇게 리턴하면 (props)⇒{ return props.borderColor } 의 값이 === 'red' 가 되고 결국 우리 눈에는 복잡해보이지만, 브라우저는 border: 1px solid red 라는 코드로 인식하여 스타일링이 되는 것 입니다.

🔥 [어려울 수 있지만 도전!] Swtich문과 map을 사용해서 리팩토링

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

const StContainer = styled.div`
  display: flex;
`;

const StBox = styled.div`
  width: 100px;
  height: 100px;
  border: 1px solid ${(props) => props.borderColor};
  margin: 20px;
`;

// 박스의 색을 배열에 담습니다.
const boxList = ["red", "green", "blue"];

// 색을 넣으면, 이름을 반환해주는 함수를 만듭니다.
const getBoxName = (color) => {
  switch (color) {
    case "red":
      return "빨간 박스";
    case "green":
      return "초록 박스";
    case "blue":
      return "파란 박스";
    default:
      return "검정 박스";
   }
};
const App = () => {
  return (
    <StContainer>
	  {/* map을 이용해서 StBox를 반복하여 화면에 그립니다. */}
      {boxList.map((box) => (
        <StBox borderColor={box}>{getBoxName(box)}</StBox>
      ))}
    </StContainer>
  );
};

export default App;

GlobalStyles(전역 스타일링)

전역 스타일링이란?

styled components는 컴포넌트 내에서만 활용할 수 있다.

가끔 우리는 프로젝트를 아우르는, 공통적으로 들어가야 할 스타일을 적용해야 할 필요도 있습니다.

그럴 경우 ‘전역적으로(globally)’ 스타일을 지정 라고 표현하는데, 그럴 때 적용하는 방법이 바로 전역 스타일링입니다.

컴포넌트 단위 스타일링

import styled from "styled-components";

function TestPage(props) {
  return (
    <Wrapper>
      <Title>{props.title}</Title>
      <Contents>{props.contents}</Contents>
    </Wrapper>
  );
}

const Title = styled.h1`
  font-family: "Helvetica", "Arial", sans-serif;
  line-height: 1.5;
  font-size: 1.5rem;
  margin: 0;
  margin-bottom: 8px;
`;

const Contents = styled.p`
  margin: 0;
  font-family: "Helvetica", "Arial", sans-serif;
  line-height: 1.5;
  font-size: 1rem;
`;

const Wrapper = styled.div`
  border: 1px solid black;
  border-radius: 8px;
  padding: 20px;
  margin: 16px auto;
  max-width: 400px;
`;

export default TestPage;

<h1>, <p>, <div> 태그는 각각 <Title />, <Contents />, <Wrapper />에서 새롭게 스타일링 됬습니다.

만일 규모가 좀 큰 프로젝트라고 한다면 공통적으로 적용되는 스타일링 부분은 빼줄 필요가 있습니다.

우리의 경우는 글꼴(font)와 line-height를 공통 요소라 가정하고 GlobalStyles을 적용할 수 있어야한다.

GlobalStyles 적용

GlobalStyle.jsx

import { createGlobalStyle } from "styled-components";

const GlobalStyle = createGlobalStyle`
  body {
    font-family: "Helvetica", "Arial", sans-serif;
    line-height: 1.5;
  }
`;

export default GlobalStyle;

App.jsx

import GlobalStyle from "./GlobalStyle";
import BlogPost from "./BlogPost";

function App() {
	const title = '전역 스타일링 제목입니다.';
	const contents = '전역 스타일링 내용입니다.';
  return (
    <>
      <GlobalStyle />
      <BlogPost title={title} contents={contents} />
    </>
  );
}

export default App;

styled-components는 어려우 부분이아니라 익숙하지 않는 것이여서 계속 반복해서 사용하다보면은 익숙해 질 수 있을 것 이닷..!!

0개의 댓글