router 파트를 학습하면서 대대적인 파일의 변화가 있었다.
많은 게 바뀌어서 초큼 어지럽 ^^,,기 때문에 현재 파일 상태를 점검한 다음,
영화 제목 클릭 시 Detail 페이지로 넘어가게 하는 내용을 정리하겠다.
-App.js
-routes 폴더 안에 Home.js랑 Detail.js
-components 폴더 안에 Movie.js
-index.js
App.js
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='/' element={<Home />} />
<Route path='/movie' element={<Detail />} />
</Routes>
</Router>
);
}
export default App;
react-router-dom에서 import할 BrowserRouter as Router, Routes, Route와 같이 필요한 컴포넌트를 먼저 선언해준다.
이 컴포넌트들은 url을 바라보고 있다. 리액트 라우터가 해당 경로일 때(url이 바뀌면) 무엇을 보여줄지 결정하는 것이다.
즉,
url 마지막에 "/"을 붙이면 Home 컴포넌트를 보여주고,
url 마지막에 "/movie"를 붙이면 Detail 컴포넌트를 보여주는 것이다.
Home.js
import { useEffect, useState } from "react";
import Movie from "../components/Movie";
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=9&sort_by=year"
)
).json();
setMovies(json.data.movies);
setLoading(false);
};
useEffect(() => {
getMovies();
}, []);
console.log(movies);
return (
<div>
{loading ? (
<h1>Loading...</h1>
) : (
movies.map((movie) => (
<Movie
key={movie.id}
coverImg={movie.medium_cover_image}
title={movie.title}
summary={movie.summary}
genres={movie.genres}
year={movie.year}
/>
))
)}
</div>
);
}
export default Home;
기존에 App.js에 있던 것들을 싹다 Home 파일로 옮겨왔다.
Detail.js
function Detail() {
return <h1>Detail</h1>;
}
export default Detail;
우선은 Detail이라는 글자만 보여주고 Home이 있는 페이지와 구분하는 데에 의의를 두고 시작하자.
Movie.js
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
function Movie({ coverImg, title, summary, genres, year }) {
return (
<div>
<img src={coverImg} alt={title} />
<h2>
<Link to='/movie'>{title + " (" + year + ")"}</Link>
</h2>
<p>{summary}</p>
<ul>
{genres.map((g) => (
<li key={g}>{g}</li>
))}
</ul>
</div>
);
}
Movie.propTypes = {
coverImg: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
summary: PropTypes.string.isRequired,
genres: PropTypes.arrayOf(PropTypes.string).isRequired,
year: PropTypes.number.isRequired,
};
export default Movie;
Home.js에서 return 부분을 옮겨온 파일.(깔끔해지려고)
그리고 마지막 index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
App을 렌더링하는 뿌리 역할을 묵묵하게 수행하고 있는 index.js. 별다른 변화는 없다.
현황 점검 완료!
이제 url에 변수를 넣을 수 있는 다이내믹 url을 공부해보자.
Movie를 렌더링하고 있는 Home 컴포넌트로 가서,
Movie에 id라는 prop을 지정하자.
return (
<div>
{loading ? (
<h1>Loading...</h1>
) : (
movies.map((movie) => (
<Movie
key={movie.id}
id={movie.id} //🖐🏻 여기여기
coverImg={movie.medium_cover_image}
title={movie.title}
summary={movie.summary}
genres={movie.genres}
year={movie.year}
/>
))
)}
</div>
);
그리고 Movie 컴포넌트에서 id라는 prop을 인자로 넘겨 받을 수 있다.
그리고 id라는 prop을 사용할 수 있게 되는데,
여기서는 movie url 뒷부분에 사용했다.
각 영화마다 가진 고유의 id를 detail url 뒷부분에 설정할 수 있기 때문이다.
function Movie({ id, coverImg, title, summary, genres, year }) {
return (
<div>
<img src={coverImg} alt={title} />
<h2>
<Link to={`/movie/${id}`}>{title + " (" + year + ")"} </Link> //🖐🏻여기여기
</h2>
<p>{summary}</p>
<ul>
{genres.map((g) => (
<li key={g}>{g}</li>
))}
</ul>
</div>
);
}
Strive, Strive, Strive라는 영화를 클릭하면 url 뒷부분에 47540이라는 id가 뜨지만,
La Traviata라는 영화를 클릭하면 url 뒷부분에 29810이라는 id가 뜬다.
그렇다면 영화의 id를 좀 더 간편히 얻는 방법이 있을까?
Parameter를 사용하면 된다.
Detail.js에서 useParams를 import하면,
import { useParams } from "react-router-dom";
function Detail() {
const x = useParams();
console.log(x);
return <h1>Detail</h1>;
}
export default Detail;
Latraviata의 id를 얻을 수 있다.
그럼 영화의 id별로 영화의 정보 API를 가져오자.
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);
};
useEffect(() => {
getMovie();
}, []);
return <h1>Detail</h1>;
}
export default Detail;
영화의 id를 알고 있으니, title 등의 정보를 API로 fetch해 올 수가 있다.
이제 json을 받아왔으니, state에 넣어주고 영화의 상세정보를 화면에 보여주는 작업을 해보자.
다음 게시물에 잘 꾸며서 올려보겠다!