-
MovieApp 만들기) 3.Movie Detail 만들기NODE.JS 2021. 4. 27. 16:22
이번에는 메인 화면에 있는 영화를 클릭할 경우 창이 이동해서 영화의 디테일 사항을 보여주도록 한다.
만드는 순서는
1. 특정영화에 대한 정보를 가져오고
2. 영화 api 정보를 state에 넣고,
3. 전체적인 템플릿을 만들고,
4. 영화에 나오는 배우들 정보를 가져오고,
5. 가져온 정보를 state에 넣고,
6. 가져온 state의 정보를 보여주는 순으로 진행된다.
일단 view->MovieDetial->MovieDetail.js파일을 만든다.
function MovieDetail(props) { let movieId = props.match.params.movieId const [Movie, setMovie] = useState([])//이름은 Movie로 하고 array에 넣어준다. const [Casts, setCasts] = useState([]) useEffect(() => { let endpointCrew = `${API_URL}movie/${movieId}/credits?api_key=${API_KEY}` let endpointInfo = `${API_URL}movie/${movieId}?api_key=${API_KEY}` fetch(endpointInfo) .then(response => response.json()) .then(response => { console.log(response) setMovie(response) //response를 Movie에 넣어준다. }) fetch(endpointCrew) .then(response => response.json()) .then(response => { console.log('responseForCrew',response) setCasts(response.cast)//배우 정보만 가져오자. }) }, [])
일단 가져온 영화와 캐스팅의 정보들을 useState를 이용해서 가져온다.
이전시간에 grid 이용시 Movie id를 넘기기로 했는데 이를 이용해서 영화정보, 배우정보를 가져온다.
우선 App.js에 Movie Detail이 보여지도록 route를 추가해준다.
import { Route, Switch } from "react-router-dom"; import Auth from "../hoc/auth"; // pages for this product import LandingPage from "./views/LandingPage/LandingPage.js"; import LoginPage from "./views/LoginPage/LoginPage.js"; import RegisterPage from "./views/RegisterPage/RegisterPage.js"; import NavBar from "./views/NavBar/NavBar"; import Footer from "./views/Footer/Footer"; import MovieDetail from "./views/MovieDetail/MovieDetail"; //null Anyone Can go inside //true only logged in user can go inside //false logged in user can't go inside function App() { return ( <Suspense fallback={(<div>Loading...</div>)}> <NavBar /> <div style={{ paddingTop: '69px', minHeight: 'calc(100vh - 80px)' }}> <Switch> <Route exact path="/" component={Auth(LandingPage, null)} /> <Route exact path="/login" component={Auth(LoginPage, false)} /> <Route exact path="/register" component={Auth(RegisterPage, false)} /> <Route exact path="/movie/:movieId" component={Auth(MovieDetail, null)} /> //여기에 추가 </Switch> </div> <Footer /> </Suspense> ); } export default App;
그다음 MovieDetail->Sections->MovieInfo.js파일을 만들고 다음의 내용을 추가해준다. (가져올 설명들)
import React from 'react' import { Descriptions, Badge} from 'antd'; function MovieInfo(props) { let {movie} = props; return ( <Descriptions title = "Movie Info" bordered> <Descriptions.Item label = "Title">{movie.original_title}</Descriptions.Item> <Descriptions.Item label = "release_date">{movie.release_date}</Descriptions.Item> <Descriptions.Item label = "revenue">{movie.revenue}</Descriptions.Item> <Descriptions.Item label = "runtime">{movie.runtime}</Descriptions.Item> <Descriptions.Item label = "vote_average" span={2}>{movie.vote_average}</Descriptions.Item> <Descriptions.Item label = "vote_count">{movie.vote_count}</Descriptions.Item> <Descriptions.Item label = "status">{movie.status}</Descriptions.Item> <Descriptions.Item label = "popularity">{movie.popularity}</Descriptions.Item> </Descriptions> ) } export default MovieInfo
다시돌아와 movieDetail.js 파일에 사용할 정보를 입력한다.
import React from 'react'; import {useEffect, useState} from 'react'; import { API_KEY, API_URL, IMAGE_BASE_URL} from "../../Config"; import MainImage from "../LandingPage/Section/MainImage" import MovieInfo from "./Sections/MovieInfo"; import GridCards from "../commons/GridCards"; import {Row} from 'antd'; function MovieDetail(props) { //생략 }, []) return ( <div> {/* Header */} <MainImage //랜딩페이지에서의 메인이미지 특징과 동일하게 준다. (State이름만 Movie로 바꿔준다.) images={`${IMAGE_BASE_URL}w1280${Movie.backdrop_path}`} title={Movie.original_title} text={Movie.overview} /> {/* Body */} <div style={{width:'85%', margin:'1rem auto'}}> {/* Movie Info */} <MovieInfo movie = {Movie} /> </div> </div> ) } export default MovieDetail
메인 이미지는 랜딩페이지에서의 MainImage의 구성과 비슷하다. 특정 영화의 타이틀과 정보만 가져오면 된다.
다음은 actors Grid파트를 추가해준다. (배우정보)
{/* Actors Grid */} <div style = {{ display:'flex', justifyContent:'center', margie:'2rem'}}> <button onClick={toggleActorView}> Toggle Actor View </button> </div> {ActorToggle && //actorToggle이 true 일때만 이 부분을 보여주자. <Row gutter={[16, 16]}> {Casts && Casts.map((cast, index)=> ( <React.Fragment key={index}> <GridCards image={cast.profile_path ? //posterpath가 있는 경우와 없는 경우를 나눠서 처리 `${IMAGE_BASE_URL}w500${cast.profile_path}`: null} characterName ={cast.name} /> </React.Fragment> ))} </Row> }
여기서 아랫부분의 그리드파트는 랜딩페이지에서와 매우 유사하기 때문에 랜딩페이지 부분의 그리드 파트를 특정하게 landingPage prop을 추가해서 그리드 파트에서 상황에 맞게 따로 적용되도록 바꿔준다.
{/* {Main Image} */} {MainMovieImage && //메인무비 이미지 가져온 다음에 실행하라는 의미(backdrop_path알기 위해서) <MainImage images={`${IMAGE_BASE_URL}w1280${MainMovieImage.backdrop_path}`} title={MainMovieImage.original_title} text={MainMovieImage.overview} /> } <div style ={{ width: '85%', margin: '1rem auto'}}> <h2> Movies by latest </h2> <hr /> {/* {Movie Grid Cards} */} <Row gutter={[16, 16]}> {Movies && Movies.map((movie, index)=> ( <React.Fragment key={index}> <GridCards landingPage image={movie.poster_path ? //posterpath가 있는 경우와 없는 경우를 나눠서 처리 `${IMAGE_BASE_URL}w500${movie.poster_path}`: null} //고유의 영화정보 입력을 위해 아이디 필요 movieId = {movie.id} movieName ={movie.original_title} /> </React.Fragment> ))} </Row> </div> <div style={{display:'flex', justifyContent:'center'}}> <button onClick={loadMoreItems}> Load More </button> </div> </div>
import React from 'react' import {Col} from 'antd'; function GridCards(props) { if(props.landingPage){//이부분은 prop이 랜딩페이지일때 실행 return ( //넓이에 따라서 사진 갯수를 정한다.총 넓이를 24로 보고, 넓을 때는 한개당 6차지(4개), 중간은 8차지(3개), 제일 작을때는 하나만 보이도록 설정 <Col lg={6} md={8} xs={24}> <div style={{position:'relative'}}> <a href={`/movie/${props.movieId}`}> <img style={{width:'100%', height:'320px'}} src= {props.image} alt={props.movieName}/> </a> </div> </Col> ) } else{//이 부분은 prop이 액터나 다른 부분일 때 실행 return ( <Col lg={6} md={8} xs={24}> <div style={{position:'relative'}}> <img style={{width:'100%', height:'320px'}} src= {props.image} alt={props.characterName}/> </div> </Col> )} } export default GridCards
나머지 토글 버튼을 눌렀을 때 배우의 사진이 나타나도록 토글 함수를 적용해준다.
import React from 'react'; import {useEffect, useState} from 'react'; import { API_KEY, API_URL, IMAGE_BASE_URL} from "../../Config"; import MainImage from "../LandingPage/Section/MainImage" import MovieInfo from "./Sections/MovieInfo"; import GridCards from "../commons/GridCards"; import {Row} from 'antd'; function MovieDetail(props) { let movieId = props.match.params.movieId const [Movie, setMovie] = useState([])//이름은 Movie로 하고 array에 넣어준다. const [Casts, setCasts] = useState([]) const [ActorToggle, setActorToggle] = useState(false) // ..생략 const toggleActorView = () =>{ setActorToggle(!ActorToggle)// 토글 버튼 활성화 시키기 } //..생략 {/* Actors Grid */} <div style = {{ display:'flex', justifyContent:'center', margie:'2rem'}}> <button onClick={toggleActorView}> Toggle Actor View </button> </div> {ActorToggle && //actorToggle이 true 일때만 이 부분을 보여주자. <Row gutter={[16, 16]}> {Casts && Casts.map((cast, index)=> ( <React.Fragment key={index}> <GridCards image={cast.profile_path ? //posterpath가 있는 경우와 없는 경우를 나눠서 처리 `${IMAGE_BASE_URL}w500${cast.profile_path}`: null} characterName ={cast.name} /> </React.Fragment> ))} </Row> } </div> </div> ) } export default MovieDetail
전체적인 MovieDetail.js파일을 보면
import React from 'react'; import {useEffect, useState} from 'react'; import { API_KEY, API_URL, IMAGE_BASE_URL} from "../../Config"; import MainImage from "../LandingPage/Section/MainImage" import MovieInfo from "./Sections/MovieInfo"; import GridCards from "../commons/GridCards"; import {Row} from 'antd'; function MovieDetail(props) { let movieId = props.match.params.movieId const [Movie, setMovie] = useState([])//이름은 Movie로 하고 array에 넣어준다. const [Casts, setCasts] = useState([]) const [ActorToggle, setActorToggle] = useState(false) useEffect(() => { let endpointCrew = `${API_URL}movie/${movieId}/credits?api_key=${API_KEY}` let endpointInfo = `${API_URL}movie/${movieId}?api_key=${API_KEY}` fetch(endpointInfo) .then(response => response.json()) .then(response => { console.log(response) setMovie(response) //response를 Movie에 넣어준다. }) fetch(endpointCrew) .then(response => response.json()) .then(response => { console.log('responseForCrew',response) setCasts(response.cast)//배우 정보만 가져오자. }) }, []) const toggleActorView = () =>{ setActorToggle(!ActorToggle)// 토글 버튼 활성화 시키기 } return ( <div> {/* Header */} <MainImage //랜딩페이지에서의 메인이미지 특징과 동일하게 준다. (State이름만 Movie로 바꿔준다.) images={`${IMAGE_BASE_URL}w1280${Movie.backdrop_path}`} title={Movie.original_title} text={Movie.overview} /> {/* Body */} <div style={{width:'85%', margin:'1rem auto'}}> {/* Movie Info */} <MovieInfo movie = {Movie} /> <br/> {/* Actors Grid */} <div style = {{ display:'flex', justifyContent:'center', margie:'2rem'}}> <button onClick={toggleActorView}> Toggle Actor View </button> </div> {ActorToggle && //actorToggle이 true 일때만 이 부분을 보여주자. <Row gutter={[16, 16]}> {Casts && Casts.map((cast, index)=> ( <React.Fragment key={index}> <GridCards image={cast.profile_path ? //posterpath가 있는 경우와 없는 경우를 나눠서 처리 `${IMAGE_BASE_URL}w500${cast.profile_path}`: null} characterName ={cast.name} /> </React.Fragment> ))} </Row> } </div> </div> ) } export default MovieDetail
사진으
이와 같은 영화 상세설명 페이지가 나오게 되고, toggle 버튼을 누르면 영화의 배우정보가 나오게 된다. 'NODE.JS' 카테고리의 다른 글
Youtube 만들기) 1.BoilerPlate설치하고 MongoDB 연결하기 (0) 2021.04.28 MovieApp 만들기) 5.Favorite 페이지 만들기 (0) 2021.04.27 MovieApp 만들기) 4.Favorite Button 만들기 (0) 2021.04.27 MovieApp 만들기) 2.Landing Page 만들기 (0) 2021.04.26 MovieApp 만들기) 1.Mongo Db 연결하기 (0) 2021.04.26