리액트에서 컴포넌트 만들었는데 스타일 컴포넌트에서 background 이미지만 어떻게 바꿀까?

minkyeongJ·2022년 6월 30일
0

개발 tips

목록 보기
11/20

리액트로 블로그를 리팩토링 하기위해 컴포넌트화를 하고 스타일 컴포넌트를 작성하여 코드를 작성하고 있었다. 그 중 배너를 컴포넌트로 만들었는데, 메인화면에 배경사진과 게시글마다의 배경사진을 다르게 주고싶었다. 아래의 사진처럼.

메인 배너 사진게시글 배너 사진

그런데 아차차 이게 무슨일이야! 게시글은 동적 데이터라서 public/assets 아래에 있었고 메인 배경화면은 정적데이터로 사용하여 src/assets에 있었다는 것이다!

이걸 도데체 메인배너과 게시글배너 컴포넌트로 나누지 않고, 배너 컴포넌트로만 어떻게 구현할 수 있을지 엄청난 고민을 했다.

먼저 고려한 것은 메인배너와 게시글배너가 나타내는 text정보가 다른 것이었다. <Switch>와 <Route>를 이용해서 페이지 경로에 따라 보여지는 정보가 다르게 나오도록 설정했다.

이때 고려할 것은
<BrowserRouter>를 내가 사용하려는 파일보다 상위 파일에 적어두었다면 다시 명시하지 말 것

  • 명시를 했을 때 상위폴더에 작성한 <Switch>와 <Route>가 제대로 작동하지 않는 현상이 보였다.

두 번째는 하나의 스타일 컴포넌트에서 <Route>마다 다른 결과를 보여줄 수 있도록 설정하는 것이다.
스타일드 컴포넌트도 컴포넌트이기에 props를 받아올 수가 있다. props로 값을 받아 css를 다르게 보여줄 수 있는 것이다.

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

const StyledButton = styled.button`
  padding: 0.375rem 0.75rem;
  border-radius: 0.25rem;
  font-size: 1rem;
  line-height: 1.5;
  border: 1px solid lightgray;

  color: ${(props) => props.color || "gray"};
  background: ${(props) => props.background || "white"};
`;

function Button({ children, color, background }) {
  return (
    <StyledButton color={color} background={background} Î>
      {children}
    </StyledButton>
  );
}

위의 코드를 보면 props로 값을 받아 color와 background에 설정한다.
${(props) => props.color || "gray"};
이 경우에는 props에 값이 없으면 "gray"로 설정하고 값이 있으면 props.color를 적용하라는 뜻이다.

내가 작성해본 다른 코드는 아래와 같다. bgImg라는 이름으로 값을 넘겨 페이지에 따른 배너이미지를 보여주게 만들었다.

<Switch>
    <Route exact path="/">
      <BannerStyle bgImg={mainBg}>
        <div className="max-width">
          <div className="banner-contents">
            <p className="sub-text">{subTitle}</p>
            <p className="main-text">{mainTitle}</p>
            <p className="description">
              {description}
            </p>
          </div>
        </div>
      </BannerStyle>
    </Route>
    <Route exact path="/postView/:id">
      <BannerStyle bgImg={postMainBg}>
        <div className="max-width">
          <div className="banner-contents">
            <p className="today">{monthStr} <em>{day}</em> {dayOfWeekStr}</p>
          </div>
        </div>
      </BannerStyle>
    </Route>
  </Switch>
//--------------------------------------------------------
const BannerStyle = styled.div`
	position: relative;
	background: ${(props) => `url(${props.bgImg})`} no-repeat 50% 50% / cover;

	height: 27em;
	margin-bottom: -7em;

이 답을 찾는데 꽤나 오랜 시간이 걸렸다. 누군가에게 이 글이 헤매는 시간을 단축시켜줄 하나의 힌트가 되었으면 좋겠다.

참고자료

profile
멋진 프론트엔드 개발자를 위하여!

0개의 댓글