Web/React

[ReactJS로 영화 웹 서비스 만들기] 기본 기능

분홍돼지 2024. 10. 23. 16:55

해당 내용은 노마드 코더의 강의 및 React 공식 문서, 공식문서 번역을 참고하여 작성한 글입니다.

올바르지 않은 내용이 있다면 의견 남겨주세요. 언제든지 환영입니다.

 

1. Movie 컴포넌트

import PropTypes from 'prop-types';

function Movie({key, title, image, summary, genres}) {
    return(
        <div key={key}>
        <h2>{title}</h2>
        <img src={image}/>
        <p>{summary}</p>
        <ul>
          {genres.map((genre, index) => <li>{genre}</li>)}
        </ul>
      </div>
    )
}

Movie.propTypes = {
    image: PropTypes.string.isRequired,
    key:PropTypes.number.isRequired,
    title:PropTypes.string.isRequired,
    summary:PropTypes.string.isRequired,
    genres:PropTypes.arrayOf(PropTypes.string).isRequired
}

export default Movie;

components/Movie.js

 

import { useState, useEffect } from 'react';
import Movie from '../components/Movie';


// reactRouter -> 페이지 전환하는 
function Home() {
  const [loading, setLoading] = useState(true);
  const [movies, setMovies] = useState([]);

  const getMovie = async() => {
    const response = await fetch("https://yts.mx/api/v2/list_movies.json?minimum_rating=8.8&sort_by=year");
    const json = await response.json();
    setMovies(json.data.movies);
    setLoading(false);
  }

  useEffect(() => {
    // 과거에 쓰는 방법
    // fetch("https://yts.mx/api/v2/list_movies.json?minimum_rating=9&sort_by=year")
    // .then((response) => response.json())
    // .then((json) => {
    //   setMovies(json.data.movies);
    //   setLoading(false);
    // });

    getMovie();
  }, []);

  return (
    <>
      <h1>Movie</h1>
      { loading? (
        <h1>'Loading..'</h1>
        ) : 
        (
          movies.map((item) => 
          <Movie key={item.id} title={item.title} image={item.medium_cover_image} summary={item.summary}
          genres={item.genres}/>
          )
        )
      }
    </>
  );
 
}

export default Home;

routes/Home.js

 

import logo from './logo.svg';
import './App.css';

function App() {
  return (
    
  );
}

export default App;

App.js

 

App.js는 비워두고 처음 시작시 Movie 리스트가 보여지고, url 변경 시 detail을 보여줄 수 있도록 수정한다. 이것을 위해 react-router를 이용한다.

 

2. react-router

"클라이언트 측 라우팅",  기존 웹사이트에서 브라우저는 사용자가 링크를 클릭하면 새 페이지에 대한 프로세스가 처음부터 시작된다. 반면, 클라이언트 측 라우팅을 통해 앱은 서버에서 다른 문서를 요청하지 않고도 링크 클릭을 통해 URL을 업데이트 할 수 있다. 

브라우저가 완전히 새로운 문서를 요청하거나 다음 페이지에 대한 CSS, JS 자산을 재평가할 필요가 없기 때문에 더 빠른 사용자 경험이 가능하다.

react 와 <a> 렌더링 차이

 

그러면 제목 클릭 시, Detail 페이지로 넘어가는 코드를 작성해본다.

import logo from './logo.svg';
import './App.css';
import { Route, Routes, BrowserRouter } from "react-router-dom";
import Home from './routes/Home';
import Detail from './routes/Detail';


function App() {
  return (
    <div>
      <h1>Movie Router</h1>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/movie/:thisismovieId" element={<Detail />} />
        </Routes>
      </BrowserRouter>
    </div>
  );
}

export default App;

App.js

 

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

function Movie({id, title, image, summary, genres}) {
  console.log(`${id} :: title is ${title}`);
    return(
        <div key={id}>
          <h2><Link to={`/movie/${id}`}>{title}</Link></h2>
          <img src={image}/>
          <p>{summary}</p>
          <ul>
            {genres.map((genre, index) => <li key={index}>{genre}:: {index}</li>)}
          </ul>
      </div>
    )
}

Movie.propTypes = {
    image: PropTypes.string.isRequired,
    id:PropTypes.number.isRequired,
    title:PropTypes.string.isRequired,
    summary:PropTypes.string.isRequired,
    genres:PropTypes.arrayOf(PropTypes.string).isRequired
}

export default Movie;

Movie.js

 

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

const getDetail = async(id) => {
    const response = await fetch(`https://yts.mx/api/v2/movie_details.json?movie_id=${id}`);
    const json = await response.json();
    console.log(json);
}
function Detail() {

    // 전달한 param 가져오기
    // <Route path="/movie/:thisismovieId" element={<Detail />} /> thisismovieId가 찍히게 된다.
    const { thisismovieId } = useParams();
    console.log(thisismovieId);

    useEffect(()=> {
        getDetail(thisismovieId);
    }, []);
    return (<h1>Detail!</h1>)
}

export default Detail;

Detail.js

 

  • <Routes> : <Routes>는 모든 하위 경로를 탐색하여 가장 적합한 일치 항목을 찾아 렌더링한다. 
  • <Route>
    • 라우터 생성 함수에 전달되는 개체
    • <Route path = "/teams/:teamId">
      • path는 URL과 일치하는 경로이다. URL, href 와 일치하는지 확인한다. 
      • : 는 동적세그먼트다. 경로가 URL과 일치하면 동적 세그먼트는 URL에 파싱한다. 이 세그먼트는 useParams() 에서 가져올 수 있으며 - 는 사용할 수 없다.
        🚫 "/ teams-:teamId" 
        🚫 "/:category--:productId"