본문 바로가기

프론트엔드/ReactJS 시작하기

[React] Movie App(2) - 페이지 전환(dynamic url) by React Router

이전 포스팅에 이어서 페이지 전환 기능을 추가하도록 하겠습니다. 

 

우선 폴더 구조를 아래와 같이 변경한 후,  App컴포넌트에 있던 모든 로직을 Home 컴포넌트로 옮기고 App.js에서는 react-router-dom을 사용해서 컴포넌트 렌더링을 하겠습니다.

 

#react-router-dom 설치

npm install react-router-dom

#Home 컴포넌트 -> main page(영화 리스트와 영화 정보 보여주기, 이전 App 컴포넌트 로직들을 Home 컴포넌트로 옮김)

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.5&sort_by=year'
        )
      ).json()
      setMovies(json.data.movies)
      setLoading(false)
    
    }
    console.log(movies)
    useEffect(()=>{
      getMovies();
    },[])
    return (
     <div>
       {loading ? <h1>Loading...</h1> :
        <div>
          {movies.map((movie)=>(
            <Movie 
              key={movie.id}
              coverImg={movie.medium_cover_image}
              title={movie.title}
              summary={movie.summary}
              genres={movie.genres} 
            />
            
          ))}
        </div>
       }
     </div>
    );
}
export default Home;

#Movie 컴포넌트 -> 부모 컴포넌트인 Home컴포넌트에서 props로 영화 정보를 받아와서 정보를 브라우저에 출력해주는 컴포넌트

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((genre)=>(
              <li key={genre}>{genre}</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;

#Detail 컴포넌트  -> Home 컴포넌트에서 영화 제목을 눌렀을 때, 그 영화에 대한 정보를 더 자세하게 보여주는 컴포넌트

import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";

function Detail(){
    const { id }  = useParams();
    const [loading, setLoading] = useState(true);
    const [movies, setMovies] = useState([]);
    const getMovie = async() => {
        const json = await(
            await fetch(`https://yts.mx/api/v2/movie_details.json?movie_id=${id}`)
        ).json();
        setLoading(false);
        console.log(json);
        setMovies(Object.values(json.data.movie));
        console.log(movies);

    }
    console.log(movies)
    useEffect(()=>{
       getMovie();
    },[])
    return (
       <div>
          {loading?<h1>Loading...</h1>: 
            <div>
                <h1>{movies[3]}</h1>
                <img src={movies[21]}></img>
                <h2>평점 : {movies[8]}</h2>
                <h2>요약</h2>
                <p>{movies[13]}</p>
            </div>
          }
          
          
       </div>
          
    
    )
}
export default Detail;

 

#App.js ->  Home, Detail 컴포넌트 rendering By react-router-dom

[ * 참고 : react-router-dom이 버전 6로 업그레이드되면서, Switch를 더이상 지원을 안하게 됐으며 Switch -> routes로 바뀜. 또한 component도 element로 바꼈음

#Routes는 Route(url)를 찾고 Route를 찾으면 컴포넌트를 렌더링하여 한 번에 하나의 컴포넌트만 렌더링 할 수 있도록 해주는 컴포넌트  #Link는 a href=""(html) 대신에 Link to={<Component />}로 사용하고 브라우저 새로고침 없이 유저를 다른 페이지로 이동시켜주는 컴포넌트 ]

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

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/movie/:id" element={<Detail />} />
      </Routes>
    </Router>
  )
 
}

export default App;

 

 

 

#결과

Home Component

 

Detail Component