2023.02.15 인브로즈 유튜브 React 강의
아래와 같이 화면 구성하기.
import React from 'react';
import Product from '../components/Product';
function ProductPage(props) {
const data = [
{
id: 1,
name: "양념치킨소스",
price: 3030,
url: "https://img-cf.kurly.com/cdn-cgi/image/quality=85,width=400/shop/data/goods/1597388027163l0.jpg",
alt: "상품이미지"
},
{
id: 2,
name: "시나몬 러스크",
price: 3030,
url: "https://img-cf.kurly.com/cdn-cgi/image/quality=85,width=400/shop/data/goods/1653036280614l0.jpeg",
alt: "상품이미지"
},
{
id: 3,
name: "양념치킨소스",
price: 3030,
url: "https://img-cf.kurly.com/cdn-cgi/image/quality=85,width=400/shop/data/goods/1576039512426l0.jpg",
alt: "상품이미지"
}
]
return (
<div>
{data.map((d) =>
<Product
key={d.id}
name={d.name}
price={d.price}
url={d.url}
alt={d.alt}
/>
)}
</div>
);
}
export default ProductPage;
✨ map 사용할때는 꼭 key 값 주기
import React from 'react';
function Product(props) {
return (
<div>
<img src={props.url} alt={props.alt} />
<div>{props.name}</div>
<div>{props.price}</div>
</div>
);
}
export default Product;
위에 처럼 props로 명명하면 props.url,props.name ...
props가 중복되어 사용되게 된다.
그리고 함수 선언부와 return 사이에 로직이 길어지게 되면
이 함수가 어떤 props를 받는지 하나하나 찾아서 확인해야하는
번거로움이 있기 때문에 객체 구조 분해 할당을 진행해서 코드를 작성하자.
import React from 'react';
function Product({url, alt, name, price}) {
return (
<div>
<img src={url} alt={alt} />
<div>{name}</div>
<div>{price}</div>
</div>
);
}
export default Product;
Component, JSX, Props 활용하여 간단한 영화 웹을 만들어보자.
회원가입 후 인증 key 받아서 사용 가능.
tmdb api에서 받아온 더미 데이터 넣어주기
// 사용한 API : TMDB 현재 한국에서 상영 중인 영화 API
// API Document : https://developers.themoviedb.org/3/movies/get-now-playing
// Request : https://api.themoviedb.org/3/movie/now_playing?api_key=c4e59022826dc465ea5620d6adaa6813&language=ko&page=1®ion=KR
// 아래는 Response Data
export const dummy = {
dates: { maximum: "2022-06-29", minimum: "2022-05-12" },
page: 1,
results: [
{
adult: false,
backdrop_path: "/wo3l9p0S7pcvwlzlndtKgq0peRJ.jpg",
genre_ids: [28, 12, 878],
id: 507086,
original_language: "en",
original_title: "Jurassic World Dominion",
overview:
"공룡들의 터전이었던 이슬라 누블라 섬이 파괴된 후, 마침내 공룡들은 섬을 벗어나 세상 밖으로 출몰한다. 지상에 함께 존재해선 안 될 위협적 생명체인 공룡의 등장으로 인류 역사상 겪어보지 못한 사상 최악의 위기를 맞이한 인간들. 지구의 최상위 포식자 자리를 걸고 인간과 공룡의 최후의 사투가 펼쳐진다.",
popularity: 2133.719,
poster_path: "/odxdUZWZ7fBfy3ZRj063wuJnZvo.jpg",
release_date: "2022-06-01",
title: "쥬라기 월드: 도미니언",
video: false,
vote_average: 6.7,
vote_count: 727,
},
{
adult: false,
backdrop_path: "/odJ4hx6g6vBt4lBWKFD1tI8WS4x.jpg",
genre_ids: [28, 18],
id: 361743,
original_language: "en",
original_title: "Top Gun: Maverick",
overview:
"최고의 파일럿이자 전설적인 인물 매버릭은 자신이 졸업한 훈련학교 교관으로 발탁된다. 그의 명성을 모르던 팀원들은 매버릭의 지시를 무시하지만 실전을 방불케 하는 상공 훈련에서 눈으로 봐도 믿기 힘든 전설적인 조종 실력에 모두가 압도된다. 매버릭의 지휘 아래 견고한 팀워크를 쌓아가던 팀원들에게 국경을 뛰어넘는 위험한 임무가 주어지자 매버릭은 자신이 가르친 동료들과 함께 마지막이 될지 모를 하늘 위 비행에 나서는데…",
popularity: 938.073,
poster_path: "/jMLiTgCo0vXJuwMzZGoNOUPfuj7.jpg",
release_date: "2022-06-22",
title: "탑 건: 매버릭",
video: false,
vote_average: 8.3,
vote_count: 1219,
},
...
App.js에서 넘겨주는 props 보여줄 UI 정의
import React from 'react';
//movieDummy 데이터에 포스터 이미지 경로가 풀경로가 아니기 때문에 베이스 경로 미리 선언
const IMG_BASE_URL = "https://image.tmdb.org/t/p/w1280/";
function Movie({ title, poster_path, vote_average }) {
return (
<div className='movie-container'>
<img src={IMG_BASE_URL + poster_path} alt="영화포스터" />
<div className='movie-info'>
<h4>{title}</h4>
<span>{vote_average}</span>
</div>
</div>
);
}
export default Movie;
Movie컴포넌트에 전달할 데이터 추가.
movieDummy를 dummy라는 이름으로 import하고
map( ) 함수를 이용하여 movieDummy 데이터 끌고온 후
Movie 컴포넌트에 전달
import { dummy } from './movieDummy';
import Movie from './components/Movie';
function App() {
return (
<div>
<div className='app-container'>
{
dummy.results.map((item) => {
return (
<Movie
title={item.title}
poster_path={item.poster_path}
vote_average={item.vote_average}
/>
)
})
}
</div>
</div>
);
}
export default App;
css 수정
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color:bisque;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
.movie-container {
width: 250px;
margin: 20px;
background: beige;
}
.movie-container img {
max-width: 100%;
height: 85%;
}
.app-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.movie-info {
display: flex;
padding: 20px;
justify-content: space-between;
align-items: center;
}
.movie-info h4 {
margin: 0;
}
✨💕😁😊😘👌😍❤️👍완료