영화 소개 메인페이지와 디테일 페이지를 완성하는 코드이다. 결과 화면은 위와 같다.
각각의 파일을 하나씩 설명하겠다.
위의 두 페이지를 연결하는 코드이다. 다만 강의에 나온 Switch를 리액트가 더이상 지원하지 않게 되면서, 대신 Routes를 사용했다.많은 변화가 필요하지 않다.
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
//각 화면 불러오기
import Detail from "./routes/Detail";
import Home from "./routes/Home";
function App() {
return (
<Router>
<Routes>
<Route path="/movie/:id" element={<Detail/>} />
//디테일. 동적으로 해당하는 id의 페이지를 보여준다. Detail.js 참조
<Route path="/" element={<Home/>} /> //메인
</Routes>
</Router>
);
}
export default App;
이 방식이 싫으면 npm i react-router-dom@5.3.0
커맨드를 사용하면 (아마) Switch도 될 것이다.
다음은 메인화면이다. 영화 정보를 불러오고, 컴포넌트에 필요한 props를 전달하는 것을 포함한다.
import { useEffect, useState } from "react";
import Movie from "../components/Movie";
import styles from "./Home.module.css";
function Home() {
const [loading, setLoading] = useState(true);
//로딩창 설정
const [movies, setMovies] = useState([]);
const getMovies = async () => {
const json = await (
await fetch(
`https://yts.mx/api/v2/list_movies.json?minimum_rating=8.8&sort_by=year`
)
).json();
setMovies(json.data.movies);
setLoading(false);
//로딩중을 풀어준다.
};
//응답을 받아와 json 파일에 저장한다. 평점 8.8 이상만 저장한 것을 알 수 있다.
useEffect(() => {
getMovies();
}, []);
return (
<div className={styles.container}>
{loading ? (
//로딩중이 아니라면 영화들을 보여줄 것이다.
<div className={styles.loader}>
<span>Loading...</span>
</div>
) : (
<div className={styles.movies}>
{movies.map((movie) => (
//mpp을 사용해 배열을 변형/여기서 배열은 Movie 컴포넌트
<Movie
key={movie.id}
//고유한 값인 id 사용. props로 정보를 보낸다.
id={movie.id}
year={movie.year}
coverImg={movie.medium_cover_image}
title={movie.title}
summary={movie.summary}
genres={movie.genres}
//상영연도, 이미지, 제목, 요약, 장르를 가져왔다.
/>
))}
</div>
)}
</div>
);
}
export default Home;
이제 받아온 값을 기반으로 각 영화를 컴포넌트로 작성한다.
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
import styles from "./Movie.module.css";
function Movie({ id, coverImg, title, year, summary, genres }) {
//받아온 props들은 전부 가져온다.
return (
<div className={styles.movie}>
<img src={coverImg} alt={title} className={styles.movie__img} />
//포스터
<div>
<h2 className={styles.movie__title}>
<Link to={`/movie/${id}`}>{title}</Link>
//제목. 그런데 Detail 페이지로 가는 링크가 걸려있다.
</h2>
<h3 className={styles.movie__year}>{year}</h3>
<p>{summary.length > 235 ? `${summary.slice(0, 235)}...` : summary}</p>
//요약은 너무 길지 않도록 235자에서 끊고 ...으로 축약한다.
<ul className={styles.movie__genres}>
{genres.map((g) => (
<li key={g}>{g}</li>
))}
</ul>
</div>
</div>
);
}
Movie.propTypes = {
//propTypes를 보기 위한 코드이다.
id: PropTypes.number.isRequired,
coverImg: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
summary: PropTypes.string.isRequired,
genres: PropTypes.arrayOf(PropTypes.string).isRequired,
};
export default Movie;
영화의 상세설명을 보여주는 파일이다. 원하는 방식으로 구성하면 된다.
import { useEffect } from "react";
import { useParams } from "react-router-dom";
function Detail() {
const { id } = useParams();
const getMovie = async () => {
const json = await (
await fetch(`https://yts.mx/api/v2/movie_details.json?movie_id=${id}`)
).json();
console.log(json);
};
//props 값에 해당하는 상세설명을 가져온다.
useEffect(() => {
getMovie();
}, []);
return <h1>Detail</h1>;
}
export default Detail;
여기에 적절한 css 파일을 더하게 되면 위의 웹사이트가 나온다.