-
영화목록 (Netflix) 앱 6 - 영화 추천 페이지 만들기프로젝트/영화 목록 (Netflix) 앱 2021. 11. 24. 15:35728x90
* 영화 추천 페이지 라우트 추가하기
import React from "react" import ReactDOM from "react-dom" import { BrowserRouter, Route, Routes } from "react-router-dom" import { Register, Login, Home, Detail, Recommendation } from 'pages' import './index.css' const App = () => { return ( <div> <Routes> <Route path='/' element={<Register/>}/> <Route path="/login" element={<Login/>}/> <Route path="/home" element={<Home/>}/> <Route path='/detail' element={<Detail/>}/> <Route path='/recommend' element={<Recommendation/>}/> </Routes> </div> ); }; ReactDOM.render(<BrowserRouter> <App /> </BrowserRouter>, document.getElementById("app"));
index.js 파일을 위와 같이 수정하자!
import { Register, Login, Home, Detail, Recommendation } from 'pages'
Recommendation 페이지 컴포넌트를 추가로 임포트한다.
<Route path='/recommend' element={<Recommendation/>}/>
영화추천 페이지에 대한 라우트를 추가한다.
* 영화추천 페이지 구현하기
export { default as Register } from './Register' export { default as Login } from './Login' export { default as Home } from './Home' export { default as Detail } from './Detail' export { default as Recommendation } from './Recommendation'
pages > index.js 파일에 Recommendation 페이지 컴포넌트를 내보낸다.
import React from 'react' const Recommendation = () => { return ( <div>Recommendation page</div> ) } export default Recommendation
pages 폴더에 Recommendation.js 파일을 생성하고 위와 같이 작성하자!
* 네비게이션 바 만들기
components 폴더에 아래 파일을 추가한다.
import React from 'react' import './Menu.css' function Menu({children}){ return ( <div className='Menu-container'>{children}</div> ) } export default Menu
Menu.js 파일을 위와 같이 작성하자!
.Menu-container{ width: 100%; height: 70px; color: #a9a9a9; box-shadow: 0px 2px 10px rgba(255, 255, 255, 0.35); position: fixed; z-index: 1; display: flex; justify-content: flex-end; align-items: center; padding: 10px; box-sizing: border-box; }
Menu.css 파일을 위와 같이 작성하자!
export { default as Input } from './Input' export { default as Movie } from './Movie' export { default as Loading } from './Loading' export { default as Button } from './Button' export { default as Menu } from './Menu'
components > index.js 파일에 Menu 컴포넌트를 내보낸다.
* 홈화면에서 추천 페이지로 이동하기
import React, { useState, useEffect } from 'react' import { Link, useNavigate } from 'react-router-dom' import { Movie, Loading, Input, Button, Menu } from 'components' import './Home.css' const Home = () => { const [loading, setLoading] = useState(true) const [movies, setMovies] = useState([]) const [query, setQuery] = useState('') const [isSorted, setIsSorted] = useState(-1) const navigate = useNavigate() useEffect( () => { fetch('https://yts.mx/api/v2/list_movies.json?limit=20') .then( res => res.json()) .then( result => { const {data: {movies}} = result console.log(movies) setLoading(false) setMovies(movies) }) }, []) const handleChange = (e) => { const { value } = e.target setQuery(value) } const sortByYear = (e) => { setIsSorted(isSorted * -1) } const homeUI = movies .filter(movie => { const title = movie.title.toLowerCase() const genres = movie.genres.join(' ').toLowerCase() const q = query.toLowerCase() return title.includes(q) || genres.includes(q) }) .sort( (a, b) => { return (b.year - a.year) * isSorted; }) .map(movie => <Link key={movie.id} to='/detail' state={{ movie }} style={{ textDecoration: 'none', color: 'white'}} > <Movie title={movie.title} genres={movie.genres} cover={movie.medium_cover_image} summary={movie.summary} year={movie.year} /> </Link> ) const toRankPage = () => { navigate('/recommend', { state: { movies }}) } return ( <> {loading? <Loading/>: <div className='Home-container'> <Menu> <Button handleClick={toRankPage}>Rank</Button> </Menu> <div className='Home-contents'> <Input name='search' type='text' placeholder='Search movies ...' value={query} onChange={handleChange}/> <Button handleClick={sortByYear}>정렬</Button> <div className='Home-movies'>{homeUI}</div> </div> </div>} </> ) } export default Home
Home.js 파일을 위와 같이 수정하자!
import { Link, useNavigate } from 'react-router-dom'
추천 페이지로 이동하기 위하여 useNavigate 함수를 추가한다.
import { Movie, Loading, Input, Button, Menu } from 'components'
네비게이션 바를 보여주기 위하여 Menu 컴포넌트를 임포트한다.
const navigate = useNavigate()
useNavigate 함수를 실행하면 다른 URL 경로로 이동할 수 있는 navigate 함수를 반환한다.
const toRankPage = () => { navigate('/recommend', { state: { movies }}) }
Rank 버튼을 클릭하면 실행되는 이벤트핸들러 함수이다. 버튼을 클릭하면 추천 페이지로 이동하면서 서버에서 가져온 영화목록(movies) 데이터를 추천 페이지로 전달한다. 그러면 추천 페이지에서 영화목록(movies) 데이터를 사용할 수 있다. navigate 함수의 2번째 인자로 객체를 설정하고, state 프로퍼티에 객체 형태로 전달할 데이터를 설정할 수 있다.
<Menu> <Button handleClick={toRankPage}>Rank</Button> </Menu> <div className='Home-contents'> <Input name='search' type='text' placeholder='Search movies ...' value={query} onChange={handleChange}/> <Button handleClick={sortByYear}>정렬</Button> <div className='Home-movies'>{homeUI}</div> </div>
Menu 컴포넌트를 추가로 렌더링한다. children props 로 Button 컴포넌트를 전달하여 추천 페이지로 이동할 수 있도록 하였다. 그밖에 기존 컴포넌트들은 Home-contents 라는 클래스명을 가진 div 요소로 감싸서 스타일을 적용하였다.
.Home-container{ background: url('../assets/images/background.jpg'); width: 100%; text-align: center; border: 1px solid black; } .Home-contents{ /* border: 5px solid orange; */ margin-top: 100px; } .Home-movies{ display: flex; flex-wrap: wrap; justify-content: center; align-items: center; width: 60%; margin: 0px auto; text-align: center; }
Home.css 파일을 위와 같이 수정하자! Home-contents 클래스명에 대한 스타일이 추가되었다.
import React from 'react' import { useLocation } from 'react-router-dom' const Recommendation = () => { const location = useLocation() const { movies } = location.state console.log(movies) return ( <div>Recommendation page</div> ) } export default Recommendation
Recommendation.js 파일을 위와 같이 수정하자!
import { useLocation } from 'react-router-dom'
홈화면에서 전달받은 movies 데이터를 조회하기 위하여 useLocation 함수를 임포트한다.
const location = useLocation() const { movies } = location.state console.log(movies)
상세페이지에서와 같이 홈화면에서 전달받은 movies 데이터를 조회하기 위하여 location 객체의 state 프로퍼티에 접근한다.
* 추천 페이지에 평점이 높은 영화 보여주기
import React from 'react' import './Movie.css' const Movie = ({ title, genres, cover, summary, year, rating }) => { return ( <div className='movie-container'> <img src={cover} alt={title}></img> <h3>{title} ({year})</h3> <h4>{genres.join(" ")}</h4> <h4>{rating}</h4> </div> ) } export default Movie
Movie.js 파일을 위와 같이 수정하자! rating props 를 추가해서 화면에 영화 평점을 보여줄 수 있도록 한다.
import React from 'react' import { useLocation, Link } from 'react-router-dom' import { Movie } from 'components' import './Recommendation.css' const Recommendation = () => { const location = useLocation() const { movies } = location.state console.log(movies) const bestMovies = movies .sort( (a, b) => { return (b.rating - a.rating); }) .slice(0, 3) .map(movie => <Link key={movie.id} to='/detail' state={{ movie }} style={{ textDecoration: 'none', color: 'white'}} > <Movie title={movie.title} genres={movie.genres} cover={movie.medium_cover_image} summary={movie.summary} year={movie.year} rating={movie.rating} /> </Link> ) return ( <div className='Recommendation-container'> <div className='Recommendation-bestmovies'>{bestMovies}</div> </div> ) } export default Recommendation
Recommendation.js 파일을 위와 같이 수정하자!
import { useLocation, Link } from 'react-router-dom'
상세페이지로 이동하기 위하여 Link 컴포넌트를 추가로 임포트한다.
import { Movie } from 'components'
Movie 컴포넌트를 사용하기 위하여 임포트한다.
import './Recommendation.css'
추천페이지에 대한 스타일을 적용하기 위하여 Recommendation.css 파일을 임포트한다.
const bestMovies = movies .sort( (a, b) => { return (b.rating - a.rating); }) .slice(0, 3) .map(movie => <Link key={movie.id} to='/detail' state={{ movie }} style={{ textDecoration: 'none', color: 'white'}} > <Movie title={movie.title} genres={movie.genres} cover={movie.medium_cover_image} summary={movie.summary} year={movie.year} rating={movie.rating} /> </Link> )
홈화면에서 영화 발매일 순으로 최신순, 과거순으로 정렬한 것처럼 동일하게 sort 메서드를 사용하여 영화 평점(rating) 을 기준으로 내림차순으로 정렬한다. slice 메서드를 사용하여 평점이 높은 영화 중에서 3개만 추출한다. Link 컴포넌트를 사용하여 특정 영화 클릭시 상세 페이지로 이동할 수 있도록 하며, 해당 영화의 데이터도 함께 전달한다.
영화평점을 보여주는 rating props 를 Movie 컴포넌트에 추가로 전달한다.
.Recommendation-container{ background: url('../assets/images/background.jpg'); width: 100%; text-align: center; border: 1px solid black; } .Recommendation-bestmovies{ display: flex; border: 1px solid orange; justify-content: center; padding: 20px; }
Recommendation.css 파일을 위와 같이 작성하자!
* 홈화면, 상세페이지에 영화 평점 추가하기
import React from 'react' import { Movie, Button } from 'components' import { useLocation } from 'react-router-dom' import './Detail.css' const Detail = () => { const location = useLocation() const { movie } = location.state const { yt_trailer_code } = movie console.log(movie) const watchMovieTrailer = () => { window.location.href = yt_trailer_code? `https://www.youtube.com/watch?v=${yt_trailer_code}`: "" } return ( <div className='Detail-container'> <div className='Detail-contents'> <Movie title={movie.title} genres={movie.genres} cover={movie.medium_cover_image} summary={movie.summary} year={movie.year} rating={movie.rating}> </Movie> <div className='Movie-info'> <p className='Movie-runtime'>Runtime {movie.runtime} min.</p> <p className='Movie-summary'>{movie.summary}</p> <a href={movie.torrents.length !== 0 ? movie.torrents[0].url : ''} download>Download Torrent</a><br/> <Button handleClick={watchMovieTrailer}>Watch Youtube trailer</Button> </div> </div> </div> ) } export default Detail
Detail.js 파일을 위와 같이 수정하자!
<Movie title={movie.title} genres={movie.genres} cover={movie.medium_cover_image} summary={movie.summary} year={movie.year} rating={movie.rating}> </Movie>
Movie 컴포넌트에 rating 속성을 추가한다.
import React, { useState, useEffect } from 'react' import { Link, useNavigate } from 'react-router-dom' import { Movie, Loading, Input, Button, Menu } from 'components' import './Home.css' const Home = () => { const [loading, setLoading] = useState(true) const [movies, setMovies] = useState([]) const [query, setQuery] = useState('') const [isSorted, setIsSorted] = useState(-1) const navigate = useNavigate() useEffect( () => { fetch('https://yts.mx/api/v2/list_movies.json?limit=20') .then( res => res.json()) .then( result => { const {data: {movies}} = result console.log(movies) setLoading(false) setMovies(movies) }) }, []) const handleChange = (e) => { const { value } = e.target setQuery(value) } const sortByYear = (e) => { setIsSorted(isSorted * -1) } const homeUI = movies .filter(movie => { const title = movie.title.toLowerCase() const genres = movie.genres.join(' ').toLowerCase() const q = query.toLowerCase() return title.includes(q) || genres.includes(q) }) .sort( (a, b) => { return (b.year - a.year) * isSorted; }) .map(movie => <Link key={movie.id} to='/detail' state={{ movie }} style={{ textDecoration: 'none', color: 'white'}} > <Movie title={movie.title} genres={movie.genres} cover={movie.medium_cover_image} summary={movie.summary} year={movie.year} rating={movie.rating} /> </Link> ) const toRankPage = () => { navigate('/recommend', { state: { movies }}) } return ( <> {loading? <Loading/>: <div className='Home-container'> <Menu> <Button handleClick={toRankPage}>Rank</Button> </Menu> <div className='Home-contents'> <Input name='search' type='text' placeholder='Search movies ...' value={query} onChange={handleChange}/> <Button handleClick={sortByYear}>정렬</Button> <div className='Home-movies'>{homeUI}</div> </div> </div>} </> ) } export default Home
Home.js 파일을 위와 같이 수정하자!
<Movie title={movie.title} genres={movie.genres} cover={movie.medium_cover_image} summary={movie.summary} year={movie.year} rating={movie.rating} />
Movie 컴포넌트에 rating 속성을 추가한다.
* 상세페이지에 네비게이션 바 추가하기
.Menu-container{ width: 100%; height: 70px; color: #a9a9a9; box-shadow: 0px 2px 10px rgba(255, 255, 255, 0.35); top: 0; left: 0; right: 0; position: fixed; z-index: 1; display: flex; justify-content: flex-end; align-items: center; padding: 10px; box-sizing: border-box; }
Menu.css 파일을 위와 같이 수정하자! top, left, right 속성을 모두 0 으로 설정한다.
import React from 'react' import { Movie, Button, Menu } from 'components' import { useLocation, useNavigate } from 'react-router-dom' import './Detail.css' const Detail = () => { const location = useLocation() const { movie } = location.state const { yt_trailer_code } = movie console.log(movie) const navigate = useNavigate() const watchMovieTrailer = () => { window.location.href = yt_trailer_code? `https://www.youtube.com/watch?v=${yt_trailer_code}`: "" } const toHomePage = () => { navigate('/home') } return ( <div className='Detail-container'> <Menu> <Button handleClick={toHomePage}>Home</Button> </Menu> <div className='Detail-contents'> <Movie title={movie.title} genres={movie.genres} cover={movie.medium_cover_image} summary={movie.summary} year={movie.year} rating={movie.rating}> </Movie> <div className='Movie-info'> <p className='Movie-runtime'>Runtime {movie.runtime} min.</p> <p className='Movie-summary'>{movie.summary}</p> <a href={movie.torrents.length !== 0 ? movie.torrents[0].url : ''} download>Download Torrent</a><br/> <Button handleClick={watchMovieTrailer}>Watch Youtube trailer</Button> </div> </div> </div> ) } export default Detail
Detail.js 파일을 위와 같이 수정하자!
import { Movie, Button, Menu } from 'components' import { useLocation, useNavigate } from 'react-router-dom'
상세페이지에 네비게이션 바를 구현하기 위하여 Menu 컴포넌트와 useNavigate 함수를 임포트한다.
const navigate = useNavigate()
페이지를 이동하기 위하여 useNavigate 함수를 실행하여 navigate 함수를 반환한다.
const toHomePage = () => { navigate('/home') }
Home 버턴을 클릭하면 실행되는 이벤트핸들러 함수이다. 버튼을 클릭하면 홈화면으로 이동한다.
<Menu> <Button handleClick={toHomePage}>Home</Button> </Menu>
홈화면으로 이동하기 위하여 네비게이션 바를 추가하였다. Menu 컴포넌트를 렌더링하고 Button 컴포넌트를 children 으로 전달한다.
* 영화추천 페이지에 네비게이션 바 추가하기
import React from 'react' import { useLocation, Link, useNavigate } from 'react-router-dom' import { Movie, Menu, Button } from 'components' import './Recommendation.css' const Recommendation = () => { const location = useLocation() const { movies } = location.state console.log(movies) const navigate = useNavigate() const toHomePage = () => { navigate('/home') } const bestMovies = movies .sort( (a, b) => { return (b.rating - a.rating); }) .slice(0, 3) .map(movie => <Link key={movie.id} to='/detail' state={{ movie }} style={{ textDecoration: 'none', color: 'white'}} > <Movie title={movie.title} genres={movie.genres} cover={movie.medium_cover_image} summary={movie.summary} year={movie.year} rating={movie.rating} /> </Link> ) return ( <div className='Recommendation-container'> <Menu> <Button handleClick={toHomePage}>Home</Button> </Menu> <div className='Recommendation-bestmovies'>{bestMovies}</div> </div> ) } export default Recommendation
Recommendation.js 파일을 위와 같이 수정하자!
import { useLocation, Link, useNavigate } from 'react-router-dom'
추천 페이지에 네비게이션 바를 구현하기 위하여 useNavigate 함수를 임포트한다.
import { Movie, Menu, Button } from 'components'
추천 페이지에 네비게이션 바를 구현하기 위하여 Menu, Button 컴포넌트를 임포트한다.
const navigate = useNavigate()
페이지를 이동하기 위하여 useNavigate 함수를 실행하여 navigate 함수를 반환한다.
const toHomePage = () => { navigate('/home') }
Home 버턴을 클릭하면 실행되는 이벤트핸들러 함수이다. 버튼을 클릭하면 홈화면으로 이동한다.
<Menu> <Button handleClick={toHomePage}>Home</Button> </Menu>
홈화면으로 이동하기 위하여 네비게이션 바를 추가하였다. Menu 컴포넌트를 렌더링하고 Button 컴포넌트를 children 으로 전달한다.
.Recommendation-container{ background: url('../assets/images/background.jpg'); width: 100%; text-align: center; border: 1px solid black; } .Recommendation-bestmovies{ display: flex; justify-content: center; padding: 20px; margin-top: 100px; }
Recommendation.css 파일을 위와 같이 수정하자! margin-top 속성을 100px 로 설정한다.
728x90'프로젝트 > 영화 목록 (Netflix) 앱' 카테고리의 다른 글
영화목록 (Netflix) 앱 8 - 영화 목록에서 특정 영화 삭제하기 (0) 2021.11.25 영화목록 (Netflix) 앱 7 - 좋아요 기능 추가하기 (0) 2021.11.24 영화목록 (Netflix) 앱 5 - 상세페이지 만들기 (0) 2021.11.24 영화목록 (netflix) 앱 번외편 - 사용자 정보 유효성 검증 (0) 2021.11.23 영화목록 (Netflix) 앱 4 - 검색, 정렬 구현하기 (0) 2021.11.23