React - Movie App(1)

두두두·2022년 10월 18일
0

React

목록 보기
11/21

전체 내용

https://yts.mx/api/v2/list_movies.json?minimum_rating=9&sort_by=year API 사용

api로 응답을 받기 전에 Loading 메세지를 띄우기 위해 useState로 loading 선언

	const [loading, setLoading] = useState(true);

API는 웹이 처음 로딩 될 때 한번만 불러오기 위해 useEffect 사용
API를 호출하고 fetch로 응답을 받아온다
json()으로 본문 컨텐츠를 json으로 파싱하고 출력하여 응답 데이터 구조를 확인한다

useEffect(() => {
  fetch(
    'https://yts.mx/api/v2/list_movies.json?minimum_rating=9&sort_by=year'
  )
  .then(response => response.json())
  .then(json => console.log(json));
  }, []);


data.movies에 영화 데이터가 담겨있는 것을 확인하였다
이 데이터를 담을 state를 생성하고 셋팅 함수로 데이터를 state에 저장한다
데이터를 얻어오면 loading을 false로 셋팅

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);
  });
}, []);

api의 응답을 처리하는 다른 방법이 있다
async() 와 await을 사용하는 방법이다
async()
: 이벤트 루프를 통해 비동기적으로 작동하는 함수
이 함수의 동작은 기존 웹의 동작과 무관하게 이루어진다
즉 이 함수 혼자 데이터를 가져옴
await
: async함수 내에서만 유효한 키워드로, async함수의 실행을 일시중지하고 promise가 끝난 후에 실행 재시작
(promise: 비동기 작업의 단위)

const [movies, setMovies] = useState([]);
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();
/*
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();
}, []);


movies에 있는 영화의 속성값이 위와 같다
loading이 true면 loading 메세지를 보여주고, false면 영화의 내용을 출력한다
movies.map으로 내용을 출력하려면 key값이 필요하여 id값을 사용했다
genres 속성이 없는 영화는 속성을 출력하지 않기 위해 hasOwnProperty(속성)으로 확인하여 있다면 출력하고 없다면 출력하지 않도록 하였다

전체코드

import { useEffect, useState } from "react";

function App() {
  const [loading, setLoading] = useState(true);
  const [movies, setMovies] = useState([]);
  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();*/
    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();
  }, []);

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

export default App;

컴포넌트 분리

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 response = await 
    fetch('https://yts.mx/api/v2/list_movies.json?minimum_rating=9&sort_by=year')
    const json = await response.json();*/
    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();
  }, []);

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

export default Home;

Movie.js

import PropTypes from "prop-types";

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

Movie.prototype = {
    cover_image: PropTypes.string.isRequired,
    title: PropTypes.string.isRequired,
    summary: PropTypes.string.isRequired,
    genres: PropTypes.arrayOf(PropTypes.string)
}

export default Movie

0개의 댓글