[ReactJS로 영화 웹 만들기 ]9. react router, useParams (영화 Detail 페이지 만들기)

이민선(Jasmine)·2022년 12월 16일
0
post-thumbnail

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

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을 공부해보자.

다이내믹 url (useParams)

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에 넣어주고 영화의 상세정보를 화면에 보여주는 작업을 해보자.
다음 게시물에 잘 꾸며서 올려보겠다!

profile
기록에 진심인 개발자 🌿

0개의 댓글