본문 바로가기
Web Service/React

[영화 웹 서비스 만들기] #12. React Router

by junnykim 2022. 3. 25.

~7.6 까지의 강의

 

React Router dom에 대해서 알아보자.

 

App.js

import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import Detail from "./routes/Detail";
import Home from "./routes/Home";

function App() {
  return (
    <Router>
      <Switch>
        <Route path="/hello">
          <h1>Hello</h1>
        </Route>
        <Route path="/movie">
          <Detail />
        </Route>
        <Route path="/">
          <Home />
        </Route>
      </Switch>
    </Router>
  );
}

export default App;

 

먼저 사용하기전에 import를 해야한다.

BrowserRouter는 URL의 생김새를 말한다.

HashRouter도 있는데, 이것은 뒤에 #이 붙어서 아주 작은 차이점이 생긴다.

 

Switch는 Route를 찾는 것이다. 이 때, Route는 URL을 의미한다. 즉, ~주소/여기 밑에 있는 것 

Route안에 component를 써준다. 

이때,  path="/"는 HOME으로 간다는 의미이다.

즉, user가 /에 있으면 Home Route로 이동한다. 그 후 Home을 import해주면 된다.

 

즉, React-router-dom은 component의 집합니다.

먼저 Router를 rendering하고, 그 안에 들어가는 것인 user의 URL에 따라 다르게 해준다.

Switch는 한 번에 하나의 Router만 작동하기 위해서 사용한다.

 

 

Movie.js

function Movie({ coverImg, title, summary, genres }) {
  return (
    <div>
      <img src={coverImg} alt={title} />
      <h2>
        <Link to="/movie">{title}</Link>
      </h2>
      <p>{summary}</p>
      <ul>
        {genres.map((g) => (
          <li key={g}>{g}</li>
        ))}
      </ul>
    </div>
  );
}

Router에서 다른 Router로 가게 하는 방법

영화 제목을 클릭하면 <Detail />로 가게 하고 싶다.

 

HTML의 방법처럼, a태그에 링크를 넣어 되기는 하지만,

이 방법을 쓰면 페이지 전체가 다시 재실행된다.

재실행하는 것을 피하고 싶을 때 존재하는 component가 있다.

 

Link

새로고침 없이도 다른 페이지로 이동시켜주는 component

우리가 원하는 곳 아무대서나 사용가능하다.

Link를 import해오고, Link to를 사용하면 된다.

이걸 누르면 "/movie"인 <Detail />로 이동하지만, 새로고침되지 않는다.

굉장히 빠르게 이동하는 것처럼 보인다.

 

 

즉, 전에는 App component가 모든 것을 다 하고 있었는데, 모든 logic을 별개의 자소로 옮겼다.

이 component들은 url을 바라보고 있는 일을한다.

url이 바뀌면 어떤 것을 보여줄지 Route component를 사용해서 한다.

Route 안에 component를 넣어주기만 하면 된다!

 

 

첫 화면
제목 클릭시

 


이제 동적 url에 대해서 알아보자.

동적 url은 url에 변수를 넣는 것이다.

 

App.js

import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import Detail from "./routes/Detail";
import Home from "./routes/Home";

function App() {
  return (
    <Router>
      <Switch>
      <Route path="/abot-us">
          <h1>Hello</h1>
        </Route>
        <Route path="/movie/:id">
          <Detail />
        </Route>
        <Route path="/">
          <Home />
        </Route>
      </Switch>
    </Router>
  );
}

export default App;

변수를 넣어주기 위해서, movie에 :id를 넣으면 해당하는 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=8.8&sort_by=year`
      )
    ).json();
    setMovies(json.data.movies);
    setLoading(false);
  };
  useEffect(() => {
    getMovies();
  }, []);
  return (
    <div>
      {loading ? (
        <h1>Loading...</h1>
      ) : (
        <div>
          {movies.map((movie) => (
            <Movie
              key={movie.id}
              id={movie.id}
              coverImg={movie.medium_cover_image}
              title={movie.title}
              summary={movie.summary}
              genres={movie.genres}
            />
          ))}
        </div>
      )}
    </div>
  );
}
export default Home;

Movie component를 rendering하기 때문에 여기서 id를 넘겨 주어야한다.

 

Movie.js

import PropTypes from "prop-types";
import { Link } from "react-router-dom";

function Movie({ id, coverImg, title, summary, genres }) {
  return (
    <div>
      <img src={coverImg} alt={title} />
      <h2>
        <Link to={`/movie/${id}`}>{title}</Link>
      </h2>
      <p>{summary}</p>
      <ul>
        {genres.map((g) => (
          <li key={g}>{g}</li>
        ))}
      </ul>
    </div>
  );
}

Movie.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;

클릭하면 movie 다음에 영화의 id가 나오도록한다.

어떤 id가 오는지 알면 url에 요청을 보낼 수 있다. 따라서 우리는 id가 뭔지 알아야 한다.

이제 id가 뭔지 알아내보자. 어떻게 알아낼 수 있을까?

 

제목을 누르면 Detail로 연결된다.

 

Detail.js

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;

useParams라는 함수를 불러보자.

 

받을 것을 App에서 (id라고) 알려주고, Detail에서 함수를 사용하면 React Router는 변수의 값을 바로 넘겨준다.

(Movie에서 id를 정의해서 이걸 받아오는 듯함)

id라고 했던 것을 기억한다면, 중괄호 안에 id라고 해주면 된다.

 

useParams

 

그리고 useEffect를 써서 어떠한 것에도 간섭받지 않도록 해준다.

 

제목 클릭시

 

Code Challenge

dtail스크린에는 다른 것들이 아무것도 없다.

hone에 해줬던 loading을 해주고 무비가 스테이트에 있지 않다. json을 state에 넣어주자.

여기에 영화의 상세정보들을 보여줄 수 있을 것이다.

 

 

댓글