기록하는 개발자

[React] Movie Rating Web Service-1.0.movie json api 가져오기 본문

Web/React

[React] Movie Rating Web Service-1.0.movie json api 가져오기

밍맹030 2021. 9. 23. 21:53
728x90

구현할 화면

1. axios로 api의 json을 가져오는 동안 "loading..." 이라는 문구를 띄워준다.

2. json data를 모두 가져오면 영화 목록을 보여준다.

 

< app.js >

import React from "react";
import axios from "axios";
import Movie from "./Movie";
import "./App.css";

class App extends React.Component {
    state={ 
        isLoading : true,
        movies:[]
    };

    /*axios는 항상 빠르진 않아서 
    js에게 componentDidMount 함수가 끝날 때까지 약간 시간이 걸릴 수 있다고 전달해야한다. 
    이에 getMovies 비동기 함수를 만들어 axios.get(url)이 끝날 때까지 await하도록 한다.
    */  
    getMovies = async() =>{
        const {
            data: { 
                data: { movies },
            },
        } = await axios.get("https://yts-proxy.now.sh/list_movies.json?sort_by=rating");
        this.setState({movies, isLoading : false});
    }

    componentDidMount(){
        this.getMovies();
    }

    render(){
        const {isLoading, movies} = this.state;
        return (
        <section className="container">
            {isLoading ? (
            <div className="loader">
                <span className="loaderText">Loading...</span>
            </div>
            ) : (
            <div className="movies">
                {movies.map(movie => (
                    <Movie 
                        key = {movie.id}
                        id={movie.id} 
                        year={movie.year} 
                        title={movie.title} 
                        summary={movie.summary} 
                        poster={movie.medium_cover_image}
                        genres={movie.genres}
                    />
                ))}
            </div>
            )}
        </section>
        );
    }
}

export default App;

 

< app.css >

body{
    margin :0;
    padding :0;
    height: 100%;
    margin-top : 30px;
}

.loader{
    margin-top: 320px;
    width :100%;
    height :100%;
    display :flex;
    justify-content: center;
    align-items: center;
    font-weight: 300;
}

 

< movie.js >

import React from "react";
import PropTypes from "prop-types";
import "./Movie.css";

function Movie({ year, title, summary, poster, genres}){
    return(
        <div className="movie">
            <img src={poster} alt={title} title={title}/>
            <div className="movieData">
                <div className="display">
                    <h3 className="movieTitle">{title}</h3>
                    <h5 className="movieYear">{year}</h5>
                </div>
                <ul className="movieGenre">
                    {genres.map((genre, index)=> <li key={index} className="genres_genre">{genre}</li>)}
                </ul>
                <p className="movieSummary">{summary.slice(0,200)}...</p>
            </div>       
        </div>
    ) ;
}

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

export default Movie;

< movie.css >

.movie {
    align-items: center;
    display :flex;
    float : left;
    width : 650px;
    height: 230px;
    background-color: white;
    margin-left : 45px;
    margin-bottom: 30px;
    font-weight: 300;
    padding: 20px;
    border-radius: 5px;
    color: black;
    box-shadow: 0 13px 27px -5px rgba(50, 50, 93, 0.25),
      0 8px 16px -8px rgba(0, 0, 0, 0.3), 0 -6px 16px -6px rgba(0, 0, 0, 0.025);
}

.movie img {
    position: relative;
    max-width: 150px;
    width: 100%;
    margin-right: 30px;
    box-shadow: 0 30px 60px -12px rgba(50, 50, 93, 0.25),
      0 18px 36px -18px rgba(0, 0, 0, 0.3), 0 -12px 36px -8px rgba(0, 0, 0, 0.025);
}
  
.display{
    margin: 0;
    display :flex;
}

.movieYear{
    font-weight: 300;
    margin-top : 35px;
    margin-left : 10px;
}

.movieTitle {
    float : left;
    font-size: 24px;
    font-weight: 700;
    color: #2c2c2c;
}
  
.movieGenre {
    list-style: none;
    padding: 0;
    margin: 0;
    flex-wrap: wrap;
    display: flex;
}
  
.movieGenre li{
    margin-right: 10px;
    font-size: 14px;
}

react는 자동적으로 우리가 만든 class component의 render method를 실행한다.

state 를 직접 초기화하면 직접 state를 변경하지 말라는 경고 문구가 발생한다.
→ setState를 사용하여 간접적으로 수정

- 우리가 setState를 호출하면 react는 state를 refresh하고 render function을 호출하여 변경된 정보를 보여준다.
→ react는 변화가 있는 부분만 업데이트 한다.


componenetDidMount : 처음 우리가 render를 할 때 호출되는 life cycle method

componenetDidMount 에서 data를 fetch 하기
- api로 부터 data fetching이 완료되면 "we are ready" 대신에 movie를 render 하고 map을 만들어 movie를 render한다.


fetch : 일반적으로 사람들이 js에서 data를 fetch 하는 방법
axios : fetch위에 있는 작은 layer

설치
> npm install axios

728x90