티스토리 뷰

이전에는 단일 페이지에 관해서 작업하는 일을 했다면 이번에는 어떻게 페이지를 여러개 만들고 전환하는 지에 대해서 배워보자.

  1. 영화 API를 통해서 영화정보를 가져온다. (쿼리를 통해서 원하는 정보만 가져오기) 
    • ?minimum_rating=8.5&sort_by=year //쿼리 스트링: 별점이 8.5이상인 영화 + sort year(연도별로 정렬) 가장 최신의 영화를 먼저 보이게 
  2. API 로딩이 끝나면 영화들을 보여준다.

Movie.js

import { useEffect, useState } from 'react';

function Movie() {
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    fetch(
      `https:yts.mx/api/v2/list_movies.json?minimum_rating=8.5&sort_by=year`,
    )
      .then((response) => response.json())
      .then((json) => console.log(json));
  }, []);
  return <div>{loading ? <h1>Loading...</h1> : null}</div>;
}
export default Movie;

해당 코드를 실행시켜보면 state를 사용하고 있지 않기 때문에 화면에는 Loading...만 보이지만 콘솔창에는 객체하나가 들어와있을 것이다. 해당 객체를 보면 내가 원하는 정보가 들어와 있음을 확인할 수 있다. 

json.data.movies에 내가 원하는 정보가 있음을 확인

그 다음은 state를 만들어서 원하는 객체를 받아온다. 

const [movies, setMovies] = useState([]);
  useEffect(() => {
    fetch(
      `https:yts.mx/api/v2/list_movies.json?minimum_rating=8.5&sort_by=year`
    )
      .then((response) => response.json())
      .then((json) => {
        setMovies(json.data.movies);
        setLoading(false);
      });
  }, []);
  • 기본값은 빈배열로 주며 console.log를 통해서 잘 작동하고 있는 지 확인해본다. 
  • 중요) API 로딩이 끝나면 setLoading을 false로 만들어줘야 한다.

+ API를 가져올 때 .then() 보다는 요즘 보편적으로 사용하는 것이 있는데 바로 async-await 이다. 

async-await 예제

const getMovies = async () => {
    const response = await fetch(
      `https:yts.mx/api/v2/list_movies.json?minimum_rating=8.5&sort_by=year`,
    );
    const json = await response.json();
    setMovies(json.data.movies);
    setLoading(false);
  };
  useEffect(() => {
    getMovies();
  }, []);

async-await short cut

 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);
  };
  useEffect(() => {
    getMovies();
  }, []);

다시 본론으로 돌아와서 제대로 돌아가는 지 확인해보면 console에 처음에는 [] 빈배열이다가 객체가 2번 출력되는 것을 볼 수 있는데 그 이유는 setMovies(), setLoading()을 했기 때문에 객체가 2번 출력된 것이다.  

 

이제 받은 정보들을 화면에 표시하기 위해 map()을 사용한다. 

import { useEffect, useState } from 'react';

function Movie() {
  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);
  };
  useEffect(() => {
    getMovies();
  }, []);
  console.log(movies);
  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.map((g) => (
                  <li key={g}>{g}</li>
                ))}
              </ul>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
export default Movie;

코드 설명: loading 되었을 때, setLoading을 false로 바꿔주고 맨 처음 moives는 [] 빈배열, 여기에 movies를 받아오면  API로부터 얻은 data로 State를 변경한다.  setMovies(json.data.movies); setLoading(false); 이 부분, 그 뒤에 movies.map을 하고 각각의 movie에 접근해서 그 값을 변환할 수 있게 된다. 이를 통해서 화면에 받아온 데이터를 표시한다.

 

  • 보면 map()은 고유값인 key를 주는 것이 꼭 필요하고 영화의 장르를 넣어주려고 봤더니 genres 로 배열이 들어가 있다. 그렇다면 한번 더 map()을 해야한다. map을 할 때 key값은 꼭 줘야하는데 여기서는 배열의 아이템 자체가 고유값이기 때문에 key로 아이템을 줘도 된다. // {movie.genres.map((g) => (<li key={g}>{g}</li>))}
  • img 태그를 이용해서 이미지를 로드할 수도 있다. 객체를 보면 사이즈 별로 이미지가 있는 것을 볼 수 있는데 e.g.) small/medium/large_cover_image 이미지 src 값으로 {movie.medium_cover_image} 하면 된다. 

-> state로 받은 data를 화면으로 보여주는 것을 완료했다. 그리고 state는 해당 data를 API로부터 받아온 것이다.  

 

 

댓글