-
MovieApp 만들기) 2.Landing Page 만들기NODE.JS 2021. 4. 26. 22:20
이번에는 사이트에 접속하면 바로 나타나는 랜딩페이지를 만들어 본다.
순서는 1. 전체적인 template을 만들어 놓기
2. Movie Api 에서 가져온 모든 데이터를 STATE에 넣기
3. Main Image Component를 만들기
4. Grid Card Component 만들기
5. Load More Function 만들기의 순이다.
먼저 LandingPage.js파일에 state를 이용해서 모든 데이터를 가져온다.
가져올때는 리액트의 useState를 이용한다 .
import { json } from 'body-parser'; import React , {useEffect, useState} from 'react' import { FaCode } from "react-icons/fa"; import { API_URL, IMAGE_BASE_URL} from "../../Config"; import { API_KEY} from "../../Config"; function LandingPage() { //useState를 이용해서 현재 필요한 정보들 가져온다. (괄호안은 기본값) const [Movies, setMovies] = useState([]) const [MainMovieImage, setMainMovieImage] = useState(null) const [currentPage, setcurrentPage] = useState(0) useEffect(() => { const endpoint = `${API_URL}movie/popular?api_key=${API_KEY}&language=en-US&page=1`; fetchMovies(endpoint) }, []) const fetchMovies =(endpoint)=>{ fetch(endpoint) .then(response => response.json()) .then(response => { setMovies([...Movies, ...response.results]) //LoadMore버트 누르면 원래 있던 목록에 추가하기 위해서 ...Movies(기존목록), ...response.results(새로운목록)를 더해준다. setMainMovieImage(response.results[0]) setcurrentPage(response.page) }) }
response전에 ...이 붙는 이유는 1개 이상의 여러 파일을 가져오기 위해서다.
그 다음 사진 파일을 가져오기 위해서는
landingpage -> Section -> MainImage.js파일을 만들고, 가져올 사진파일에 대한 설정을 한다.
메인 사진위에는 타이틀과 영화에 대한 설명(text)파트도 들어간다.
import React from 'react'; function MainImage(props){ return ( <div style={{background: `linear-gradient(to bottom, rgba(0,0,0,0) 39%, rgba(0,0,0,0) 41%, rgba(0,0,0,0.65) 100%), url('${props.image}'), #1c1c1c`, height: '500px', backgroundSize: '100%, cover', backgorundPosition:'center,center', width:'100%', position: 'relative' }}> <div> <div style ={{position : 'absolute', maxWidth: '500px', bottom:'2rem', marginLeft:'2rem'}}> <h2 style={{color:'white'}}> {props.title} </h2> <p style={{color:'white', fontSize:'1rem'}}> {props.text} </p> </div> </div> </div> ) } export default MainImage
다시 landingpage로 돌아와서 이미지 파트를 지정한다.
import { json } from 'body-parser'; import React , {useEffect, useState} from 'react' import { FaCode } from "react-icons/fa"; import { API_URL, IMAGE_BASE_URL} from "../../Config"; import { API_KEY} from "../../Config"; import MainImage from './Section/MainImage'; import MainMovieImage from './Section/MainImage'; //State부분 생략... return ( <div style={{ width:'100%', margin:'0'}}> {/* {Main Image} */} {MainMovieImage && //메인무비 이미지 가져온 다음에 실행하라는 의미(backdrop_path알기 위해서) <MainImage images={`${IMAGE_BASE_URL}w1280${MainMovieImage.backdrop_path}`} title={MainMovieImage.original_title} text={MainMovieImage.overview} /> }
여기서 MainMovieImage는 backdrop_path가 실행되기 전에 알려져야 하므로 &&을 사용해서 먼저 실행된 뒤에 backdrop_path정보가 사용되도록 설정하였다.
그 다음으로는 아랫 부분의 grid card 부분을 만든다.
이를 실행하기 위해서 components->views->commons->GridCard.js파일을 생성해준다.
import React from 'react' import {Col} from 'antd'; function GridCards(props) { 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> ) } export default GridCards
메인 파일 아랫 부분에 나오는 사진 파일을 설정하는데, 사진의 스타일과 col의 넓이에 따라서 large에서는 4개가 나오도록 {6} 설정,
middle 사이즈에서는 3개가 나오도록 {8} 설정, xs 사이즈의 창에서는 1개가 나오도록 {24} 설정을 해주었다.
어떤 영화인지 알고 정보를 넣기 위해서 movie id정보를 받아왔고,
어떤 영화인지 알기 위해서 영화이름을 가져오고, 영화 사진을 넣어주었다.
landing page.js 에서는 다음과 같이 구현한다.
import { json } from 'body-parser'; import React , {useEffect, useState} from 'react' import { FaCode } from "react-icons/fa"; import { API_URL, IMAGE_BASE_URL} from "../../Config"; import { API_KEY} from "../../Config"; import MainImage from './Section/MainImage'; import MainMovieImage from './Section/MainImage'; import GridCards from '../commons/GridCards'; import { Row } from 'antd'; //...생략 <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 image={movie.poster_path ? //posterpath가 있는 경우와 없는 경우를 나눠서 처리 `${IMAGE_BASE_URL}w500${movie.poster_path}`: null} movieId={movie.id}//고유의 영화정보 입력을 위해 아이디 필요 movieName={movie.original_title} /> </React.Fragment> ))} </Row> </div>
영화의 포스터가 없는 경우도 있기 때문에 영화의 포스터가 있는 경우와 없는 경우를 나눠서 처리한다.
react의 fragment에는 Key 값이 있어야 하기 때문에 인덱스 값을 넣어주었다.
Row gutter 부분은 사진과 사진사이의 가로세로 간격을 만들어 준다.
마지막으로 load more은 함수를 이용해서 구현한다.
import { json } from 'body-parser'; import React , {useEffect, useState} from 'react' import { FaCode } from "react-icons/fa"; import { API_URL, IMAGE_BASE_URL} from "../../Config"; import { API_KEY} from "../../Config"; import MainImage from './Section/MainImage'; import MainMovieImage from './Section/MainImage'; import GridCards from '../commons/GridCards'; import { Row } from 'antd'; //..생략 //다음페이지 만드는 함수 (load more) const loadMoreItems=() =>{ const endpoint = `${API_URL}movie/popular?api_key=${API_KEY}&language=en-US&page=${currentPage+1}`; fetchMovies(endpoint) } //..생략 <div style={{display:'flex', justifyContent:'center'}}> <button onClick={loadMoreItems}> Load More </button> </div> </div> ) }
버튼을 클릭하면 함수가 실행되도록 설정해 놓았다.
함수는 현재페이지에 1을 더한 페이지를 로딩하도록 하였다.
함수안의 fetchMovies는 useState에서의 중복되는 파트를 따로 빼내어서 정리한 부분이다.
전체적인 landing page의 코드는 다음과 같다.
import { json } from 'body-parser'; import React , {useEffect, useState} from 'react' import { FaCode } from "react-icons/fa"; import { API_URL, IMAGE_BASE_URL} from "../../Config"; import { API_KEY} from "../../Config"; import MainImage from './Section/MainImage'; import MainMovieImage from './Section/MainImage'; import GridCards from '../commons/GridCards'; import { Row } from 'antd'; function LandingPage() { //useState를 이용해서 현재 필요한 정보들 가져온다. (괄호안은 기본값) const [Movies, setMovies] = useState([]) const [MainMovieImage, setMainMovieImage] = useState(null) const [currentPage, setcurrentPage] = useState(0) useEffect(() => { const endpoint = `${API_URL}movie/popular?api_key=${API_KEY}&language=en-US&page=1`; fetchMovies(endpoint) }, []) const fetchMovies =(endpoint)=>{ fetch(endpoint) .then(response => response.json()) .then(response => { setMovies([...Movies, ...response.results]) //LoadMore버트 누르면 원래 있던 목록에 추가하기 위해서 ...Movies(기존목록), ...response.results(새로운목록)를 더해준다. setMainMovieImage(response.results[0]) setcurrentPage(response.page) }) } //다음페이지 만드는 함수 (load more) const loadMoreItems=() =>{ const endpoint = `${API_URL}movie/popular?api_key=${API_KEY}&language=en-US&page=${currentPage+1}`; fetchMovies(endpoint) } return ( <div style={{ width:'100%', margin:'0'}}> {/* {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 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> ) } export default LandingPage
화면으로 보게 된다면,
메인페이지(제일 먼저 보이는 사진에 타이틀과 설명이 있다.) 아래의 load more 버튼을 클릭한다면, 기존 페이지에 새로운 페이지가 더해서 목록이 생성된다. '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 만들기) 3.Movie Detail 만들기 (0) 2021.04.27 MovieApp 만들기) 1.Mongo Db 연결하기 (0) 2021.04.26