이번 프로젝트에서 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
을 지정해서 사용하고 있어서 이런 방식으로 작성했다.
앞서 소개한 대로 코드를 작성했을 경우 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
이벤트가 발생하면 진한 색상의 이미지, 발생하지 않으면 연한 색상의 이미지가 사용되고 있다.
아주 예쁘네용 (❁´◡`❁)
이제 이 정도는 아주아주 쉽다.
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
도 쓸 수 있다.
데이터를 받아와서 배경 이미지로 적용한 모습이다.
이번엔 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
라는 이름의 props
에 i
번째 별이 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
를 넘겨서 사용하는 방법을 알아봤는데, 한 번 익혀 두면 다양한 방법으로 활용이 가능하니까 두고두고 쓰기 좋을 듯!