<Route path="/movie/:id" element={<Detail />} />
영화마다 각자 다른 id를 가질 것이다.
따라서 이렇게 /movie 뒤에 /:id 를 넣어 각자 다른 영화들을 받아주게 해준다.
이제 Movie 컴포넌트에서 props를 id로 받게 변경해줘야 한다.
따라서 Home 컴포넌트로 가서 id={movie.id} 한 줄을 추가시키면 된다.
그리고 Movie 컴포넌트의 Link to="/movie">{title}/Link> 를
Link to={/movie/${id}}>{title}/Link> 로 id를 받아오게 변경해준다.
그럼 이런 식으로 영화마다 각자 다른 id 값이 넘어오는 것을 볼 수 있다.
남은 것은 정확한 id를 알아내는 것이다.
어떤 id가 오는지 알아내면 fetch url에 정확한 id 값을 줄 수 있다.
다행히도 React Router에선 이 url에 있는 값을 반환해주는 useParams 함수가 있다.
import { useParams } from "react-router-dom";
function Detail() {
const { id } = useParams();
console.log(id);
return <h1>Detail</h1>;
}
export default Detail;
Detail 컴포넌트로 가서 useParams를 다음과 같이 사용하고 콘솔창을 찍어보면
주소창에 뜨는 id와 콘솔창에 뜨는 id가 일치한 것을 볼 수 있다.
이제 남은 것은 받은 id를 가지고 API에 요청을 보내는 것이다.
import { useEffect } from "react";
import { useParams } from "react-router-dom";
function Detail() {
const { id } = useParams();
const getMovies = async () => {
const json = await (
await fetch(`https://yts.mx/api/v2/movie_details.json?movie_id=${id}`)
).json();
console.log(json);
};
useEffect(() => {
getMovies();
}, []);
return <h1>Detail</h1>;
}
export default Detail;
await 는 async 함수 안에서 사용해야해서 따로 함수를 만들었고, useEffect 안에 넣어줬다.
그리고 json을 콘솔창에 찍어보면 영화에 상세 정보를 전달 받을 수 있다.
import { useEffect, useState, useCallback } from "react";
import { useParams } from "react-router-dom";
import styled from "styled-components";
function Detail() {
const { id } = useParams();
const [loading, setLoading] = useState(true);
const [movie, setMovie] = useState([]);
const getMovie = useCallback(async () => {
const json = await (
await fetch(`https://yts.mx/api/v2/movie_details.json?movie_id=${id}`)
).json();
setMovie(json.data.movie);
setLoading(false);
}, [id]);
useEffect(() => {
getMovie();
}, [getMovie]);
return (
<MainSection>
{loading ? (
<h1>Loading...</h1>
) : (
<div>
<img src={movie.large_cover_image} alt="poster" />
<p>
🎬 Title: {movie.title}, {movie.year}
</p>
<p>✅ Download: {movie.download_count}</p>
</div>
)}
</MainSection>
);
}
const MainSection = styled.div`
position: relative;
text-align: center;
h1 {
margin-top: 360px;
}
`;
export default Detail;