넷플릭스 클론을 하면서 api 요청으로 받아온 이미지 url을 inline 방법이 아닌 styled-component로 적용하려고 든 아이디어를 정리하고자 한다.
css, module css의 사용은 어려워 보인다. 코드를 살펴보자.
// MainBanner.js
const [movie, setMovie] = useState([]);
useEffect(() => {
fetchData();
}, []);
const fetchData = async () => {
// 현재 상영중인 영화 정보 다가져오기
const request = await axios.get(requests.fetchNowPlaying);
// 여러 영화 중에 영화 하나의 id를 랜덤하게 가져오기
const movieId =
request.data.results[
Math.floor(Math.random() * request.data.results.length)
].id;
// 랜덤하게 골라진 영화의 상세 정보를 가져오기
const { data: movieDetail } = await axios.get(`movie/${movieId}`, {
params: { append_to_response: 'videos' },
});
setMovie(movieDetail);
};
movie는 api요청을 받아올 영화 정보 데이터를 넣어줄 state이다.
fetchData부분이 실제로 api를 요청하는 부분인데, banner부분이기 때문에 랜덤하게 하나의 영화의 데이터만을 movie에 넣어주고 있다.
받아온 데이터를 콘솔 찍어보면,
이러한 형태가 나오는데 저기서 backdrop_path를 https://image.tmdb.org/t/p/original/ 이 뒤에 붙여주면 해당 영화의 이미지를 얻을 수 있다.
api 통신을 통해 url을 받아오는 것이기 때문에 따로 분리된 css 파일을 통해 backgroud-image를 적용하는 방법은 좋지 않아 보인다.
사실 가장 간단한 방법이다. 바로 코드를 보면
return (
<header
style={{
backgroundImage: `url("https://image.tmdb.org/t/p/original/${movie.backdrop_path}")`,
backgroundPosition: 'top center',
backgroundSize: 'cover',
}}
>
.
.
.
</header>
)
리액트에서 변수를 이용하는 것처럼 바로 사용해서 적용할 수 있다. 간단하지만 인라인 스타일은 지양하는 것이 좋다.
이 글을 쓰게된 목적이다. 해결 방법부터 나열하면,
이 일련의 방법을 거쳤다. 코드를 봐보자.
const Banner = styled.header`
background-image: url(${(props) => props.background}); // 4
background-position: top center;
background-size: cover;
color: white;
object-fit: contian;
height: 448px;
`;
.
.
.
const [movie, setMovie] = useState([]);
const [background, setBackground] = useState(''); // 1
useEffect(() => {
fetchData();
}, []);
const fetchData = async () => {
const request = await axios.get(requests.fetchNowPlaying);
const movieId =
request.data.results[
Math.floor(Math.random() * request.data.results.length)
].id;
const { data: movieDetail } = await axios.get(`movie/${movieId}`, {
params: { append_to_response: 'videos' },
});
setMovie(movieDetail);
setBackground(
'https://image.tmdb.org/t/p/original/' + movieDetail.backdrop_path
); //2
};
.
.
.
return (
<Banner
background={background} //3
>
.
.
.
)
해당 부분에 주석으로 번호를 넣어두었다.
새로운 state를 만들자는 생각까지가 오래걸렸던 것 같다.