[React] emotion/styled 라이브러리에서 props 사용하기

예빈·2023년 4월 4일
2

React

목록 보기
3/6
post-thumbnail

이번 프로젝트에서 emotion/styled를 숨 쉬듯 사용하면서 props를 넘겨 쓰는 법을 배우게 됐고, 이 방법에 대해 기록해 보려고 한다.
여기에 작성하는 코드는 실제로 사용했던 코드가 아니라 import문 등 많은 부분을 덜어내고 변수 이름도 싹 수정한 코드기 때문에 복붙하면 휴먼 에러로 작동이 안 될 수도 있다.

파일 구조

시작하기에 앞서 src 폴더 내에 pages, styles 폴더가 있고, pages에는 React로 만든 js 파일이 들어 있으며 styles 폴더에는 emotion/styled로 만든 js 파일이 들어 있다고 가정한다.

기본 사용법

// pages/Home.js

import { HomeWrapper } from "../styles/HomeEmotion.js";
import img_src from "../assets/img.png";

const Home = () => {
  ...

  return (
    <HomeWrapper img_src={img_src}>
      <div className="img-wrapper">
      </div>
    </HomeWrapper>
  )
};

export const Home;

불필요한 코드는 빼고 React 파일에서 필요한 부분만 가져온 상태이다.
emotion/styled를 사용해 작성한 파일에서 가져올 컴포넌트에 아무 이름으로나 props를 넘겨준다.

// styles/HomeEmotion.js

import styled from "@emotion/styled";

export const HomeWrapper = styled.div`
  ...

  .img-wrapper {
	background-image: url(${(props) => props.img_src});
  }
`

그런 다음 styles/Emotion.js 안에서 ${(props) => props.변수명} 형태로 받아서 사용하면 된다.
나는 큰 컴포넌트만 const 형태로 만들고 내부에서는 <div> 태그에 className을 지정해서 사용하고 있어서 이런 방식으로 작성했다.

응용 1. hover 시에 background image 변경하기

앞서 소개한 대로 코드를 작성했을 경우 className="img-wrapper"<div>의 배경 이미지가 img_src 파일로 설정된다. 이걸 조금만 응용해보자.

// pages/Home.js

import { HomeWrapper } from "../styles/HomeEmotion.js";
import img_src from "../assets/img.png";
import img_hover_src from "../assets/img_hover.png";

const Home = () => {
  ...

  return (
    <HomeWrapper 
      img_src={img_src}
	  img_hover_src={img_hover_src}
	  >
      <div className="img-wrapper">
      </div>
    </HomeWrapper>
  )
};

export const Home;

이렇게 두 가지의 props를 넘겨준다.

// styles/HomeEmotion.js

import styled from "@emotion/styled";

export const HomeWrapper = styled.div`
  ...

  .img-wrapper {
	background-image: url(${(props) => props.img_src});
  }

  .img-wrapper:hover {
	background-image: url(${(props) => props.img_hover_src});
  }

`

그런 다음 emotion/styled로 작성한 파일에서 :hover 속성을 지정해주면 끝!

결과물

마우스 커서가 안 보이긴 하는데 hover 이벤트가 발생하면 진한 색상의 이미지, 발생하지 않으면 연한 색상의 이미지가 사용되고 있다.
아주 예쁘네용 (❁´◡`❁)

응용 2. background image에 gradient 주기

이제 이 정도는 아주아주 쉽다.
axios로 데이터를 받아온 후 그 데이터에 들어 있는 이미지를 배경으로 설정할 건데, 이 이미지에 그라데이션 효과를 주고 싶다.

// pages/Detail.js

import { useState } from "react";
import { DetailWrapper } from "../styles/DetailEmotion.js";

const Detail = () => {
  const [data, setData] = useState(null);
  
  // data를 설정해준다.
  ...

  return (
    <DetailWrapper 
      background_src={data.backgroundImg}
	  >
      <div className="detail-main">
        ...
      </div>
    </DetailWrapper>
  )
};

export const Detail;

우선 Detail.js에서 props를 넘겨주고,

import styled from "@emotion/styled";

export const DetailWrapper = styled.div`
  ...

  .detail-main {
    background-image: linear-gradient(
        to bottom,
        rgba(50, 50, 50, 0.5),
        rgba(50, 50, 50, 1)
      ),
      url(${(props) => props.background_src});
  }
`

이렇게 사용하면 요청으로 받아온 데이터에 CSS 효과 주면서 emotion/styled도 쓸 수 있다.

결과물

데이터를 받아와서 배경 이미지로 적용한 모습이다.

응용 3. 별점 렌더링하기

이번엔 0~5점의 점수를 받아와서 별점을 렌더링해볼 것이다.

// pages/Detail.js

import { useState } from "react";
import { DetailWrapper, FaStar } from "../styles/DetailEmotion.js";

import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faStar } from "@fortawesome/free-solid-svg-icons";

const Detail = () => {
  const [reviewGrade, setReviewGrade] = useState(0);
  
  ...
  
  const renderStars = (rating) => {
    const result = [];

    for (let i = 0; i < 5; i++) {
      result.push(
        <FaStar active={(i < rating).toString()} key={i}>
          <FontAwesomeIcon icon={faStar} className="fa-star" />
        </FaStar>
      );
    }

    return result;
  };

  return (
    <DetailWrapper>
      <div className="detail-main">
        ...
    	{renderStars(reviewGrade)}
      </div>
    </DetailWrapper>
  )
};

export const Detail;

위와 같이 코드를 작성했다. active 라는 이름의 propsi번째 별이 rating 값보다 작은지 여부를 넘겨주는데, .toString() 메서드로 문자열을 넘겨준다.
boolean 으로도 넘겨봤는데 이상하게 emotion/styled 파일 안에서 인식을 제대로 못하는 건지 제대로 작동하지 않아서, 일단 string 형태로 변환해서 넘겨주었다.

import styled from "@emotion/styled";
import { Common } from "./Common";

...

export const FaStar = styled.div`
  color: ${(props) =>
    props.active === "true" ? Common.colors.starColor01 : Common.colors.starColor02};
`;

emotion/styled에서는 받아온 active의 값이 "true"인지 확인하고, 맞다면 starColor01, 아니라면 starColor02로 색상을 지정하게 된다.
변수를 사용해서 전역 스타일링을 하는 방법은 여기를 참고
Detail.js에서 넘겨줄 때 문자열로 변환했기 때문에 문자열 "true" 인 것에 유의할 것! 아니면 의도대로 작동하지 않는다.
문자열 안에 넣어주는 값은 꼭 "true"가 아니어도 작동하니까 편한 대로 사용하면 된다.

결과물

각각 5점, 3점을 입력했을 때 잘 출력되는 것을 확인할 수 있다.

이렇게 emotion/styled 라이브러리에서 props 를 넘겨서 사용하는 방법을 알아봤는데, 한 번 익혀 두면 다양한 방법으로 활용이 가능하니까 두고두고 쓰기 좋을 듯!

0개의 댓글