리액트로 블로그를 리팩토링 하기위해 컴포넌트화를 하고 스타일 컴포넌트를 작성하여 코드를 작성하고 있었다. 그 중 배너를 컴포넌트로 만들었는데, 메인화면에 배경사진과 게시글마다의 배경사진을 다르게 주고싶었다. 아래의 사진처럼.
메인 배너 사진 | 게시글 배너 사진 |
---|---|
그런데 아차차 이게 무슨일이야! 게시글은 동적 데이터라서 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;
이 답을 찾는데 꽤나 오랜 시간이 걸렸다. 누군가에게 이 글이 헤매는 시간을 단축시켜줄 하나의 힌트가 되었으면 좋겠다.