본문 바로가기

JavaScript/React JS

[React JS] 간단한 Movie App 만들기1

사용할 영화 API는

 
이다.
 
import { useEffect, useState } from "react";

function App() {
  const [loading, setLoading] = useState(true);
  /* [1,2] 1이 배열의 데이터, 2가 배열 데이터를 수정하는 함수 */
  const [movies, setMovies] = useState([]);
  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);
        });
    },
    [/*이 곳이 비어있으면 render시 한번만 실행시킴 */]
  );
  console.log(movies);
  return <div>{loading ? <h1>Loading...</h1> : null}</div>;
}

export default App;

기본적인 세팅을 해준다.

1. loading을 true, false 값으로 on / off

2. movie api data값을 json화 해서 불러오기

 

여기서 이렇게 작성할 수도 있다.

  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);
      });
  }, []);
  
 ------이 방법도 가능---------
  
    const getMovies = async () => {
    const response = await fetch(
      `https://yts.mx/api/v2/list_movies.json?minimum_rating=9&sort_by=year`
    );
    const json = await response.json();
    setMovies(json.data.movies);
    setLoading(false);
  };
  useEffect(() => {
    getMovies();
  }, []);
이렇게 then을 이용한 방법 async, await를 이용해서 작성하는 방법이 있다.
  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();
  }, []);

async와 await를 더 축약시켜서 작성할 수도 있다.

 

이제 데이터를 출력해보자.

  return (
    <div>
      {loading ? (
        <h1>Loading...</h1>
      ) : (
        <div>
          {movies.map((movie) => (
            <div key={movie.id}>{movie.title}</div>
          ))}
        </div>
      )}
    </div>
  );

앞서 작성한 movies에 map함수를 적용 *JS관련 구문은 항상 {} 중괄호를 넣어준다.

영화제목이 나온다

 

추가적으로 이미지 설명문과 장르를 넣어본다면

  return (
    <div>
      {loading ? (
        <h1>Loading...</h1>
      ) : (
        <div>
          {movies.map((movie) => (
            <div key={movie.id}>
              <img src={movie.medium_cover_image} />
              <h2>{movie.title}</h2>
              <p>{movie.summary}</p>
              <ul>
                {movie.genres == null
                  ? ""
                  : movie.genres.map((i) => <li key={i}>{i}</li>)}
              </ul>
            </div>
          ))}
        </div>
      )}
    </div>
  );

이렇게 작성한다. 장르 구문은 장르가 arrary로 되어있기 때문에 map함수를 이용 새롭게 만들어준다.

단 key값으로 지정은 고유 id가 없기 때문에 genres로 key값을 대체한다.

(만약 없을 경우도 있을 수 있기 때문에 삼항 연산자 이용 null 생성) 

결과 화면

이번엔 컴포넌트를 분리해서 title을 클릭하면 상세 정보를 확인할 수 있도록 만들어보자.

Movie.js를 새로 만든다.

const Movie = ({ coverImage, title, summary, genres }) => {
  return (
    <div>
      <img src={coverImage} alt={title} />
      <h2>{title}</h2>
      <p>{summary}</p>
      <ul>{genres == null ? "" : genres.map((i) => <li key={i}>{i}</li>)}</ul>
    </div>
  );
};

export default Movie;

상기의 coverImage는 이전 medium_cover_image를 수정한 것이다. 그 외 title, summary, genres의 props는 부모 컴포넌트로부터 받아오게 된다.

추가적으로 image 요소들은 alt값을 가지기 때문에 title로 지정해 준다. *alt는 이미지의 텍스트 설명이다.

 

부모 컴포넌트 부분

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

앞서 말했듯이 coverImage의 컴포넌트는 내가 직접 만드는 것이기 때문에 임의로 지정해도 된다.

하지만 api data를 불러오기 위해 {} 안에는 원래대로 작성한다.

Key는 React JS에서만 map의 component들을 render 할 때 쓰인다.

import propTypes from "prop-types";

Movie.propTypes = {
  coverImage: propTypes.string.isRequired,
  title: propTypes.string.isRequired,
  summary: propTypes.string.isRequired,
  genres: propTypes.arrayOf(propTypes.string).isRequired,
  /* genres는 배열이기 때문에 arrayOf를 넣어준다 */
};

propTypes까지 지정해준다.

 

title 클릭 시 다른 창으로 넘어가기 위해서 React Router가 필요하다

console창에 npm i react-router-dom으로 설치한다. router으로 변경점은 다음 글에 이어서 작성하기로 한다.

 

https://github.com/ge5rg2/react-for-beginners/commit/1686e5e15a12b5433d9db971d4dbfbf76e816970

 

movie app pt2 · ge5rg2/react-for-beginners@1686e5e

Permalink This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository. Browse files movie app pt2 Loading branch information Showing 6 changed files with 293 additions and 39 deletions. +223 −0 package

github.com

 

영상 속 자세한 설명을 듣고싶다면

https://nomadcoders.co/react-for-beginners/lectures/3289

 

All Courses – 노마드 코더 Nomad Coders

초급부터 고급까지! 니꼬쌤과 함께 풀스택으로 성장하세요!

nomadcoders.co