[react] 노마드코더 영화웹서비스 제작 4.1 영화데이터 렌더링하기

unu·2021년 5월 31일
0
post-thumbnail

데이터 렌더링

비동기적 데이터 페치를 완료했다면 렌더링을 할 차례

getMovies = async() =>{
  const movies = await axios.get("https://yts.mx/api/v2/list_movies.json");
  console.log(movies);
}

데이터 찾기

⬇️ 먼저 우리가 가져온 movies를 콘솔로그 해 영화 데이터가 어디에 있는지 찾아보자

movies> data > data> movies: (20)[{...},{...},{...},{...}, ...]


getMovies = async() =>{
  const movies = await axios.get("https://yts.mx/api/v2/list_movies.json");
  console.log(movies.data.data.movies);
}

⬇️ 찾은 영화데이터의 경로로 콘솔로그 해 보자

잘 나오는 것을 확인할 수 있다.


결과는 잘 나왔지만 콘솔로그를 길게 넣는 것 보다는 미리 선언해서 갖다 넣는 것이 좋기 때문에, 정리를 해보자면...

getMovies = async() =>{
  const {data:{data:{movies}}} = await axios.get("https://yts.mx/api/v2/list_movies.json");
  console.log(movies);
}

console.log안에 있던 movies가 이전에는 "movies".data.data.movies이었다면,
지금은 movies.data.data."movies" 이거다.


위 방법과 같이 잘 동작한다.


다음에 우리가 할 것은?
데이터를 state안에 넣는것!

데이터 렌더링

먼저, 단어 때문에 '상태'라고 생각되었던 state의 개념에 다시 급 혼란이 오기 시작해서 찾아봤다.

  • React State 1. State란 무엇인가?#
  • [React] 컴포넌트의 State 란?#
  • Props VS State (eng) ##

짧게 살펴보면

매개변수처럼 컴포넌트에 전달되는 props와 달리, 함수 내에 선언된 변수같은 존재, 읽기모드인 prop과 달리 변경가능

componentDidMount(){
    this.getMovies();
  }//컴포넌트가 생성되면 겟무비 실행시킨다.
getMovies = async() =>{
  const {data:{data:{movies}}} = await axios.get("https://yts.mx/api/v2/list_movies.json");
  this.setState({movies, isLoading: false});
}

데이터 페치가 완료되면 state에 변화가 일어나는데

  state = {
    isLoading: true,
    movies: []
  };
  1. state의 movies가 우리가 불러온 위의 movies로 차게 된다.
  2. isLoading: false로 바뀌면서 "Loading..."대신 "We are ready"가 뜨는 것이다.

특히 1번의 경우

this.setState{movies: movies}//{앞은 state: 뒤는 data}
⬇️
this.setState{movies}

짧게는 이렇게 표시한다. 리액트가 똑똑해서 알아듣는다.


옆에 있는 네트워크 창을 보면 Loading...일때, pending 상태에 있는 list_movies.json이 들어오는 동시에 We are ready로 변하는 것을 볼 수 있다.

class App extends React.Component{
  state = {
    isLoading: true,
    movies: []
  };
  getMovies = async() =>{
  const {
    data: {
      data: {movies}
    }
  } = await axios.get("https://yts.mx/api/v2/list_movies.json");
  this.setState({movies, isLoading: false});
}
  componentDidMount(){
    this.getMovies();
  }
  render(){
    const {isLoading} = this.state;
    return(
    <div>
      {isLoading ? "Loading..." : "We are ready"}
    </div>
    ) 
  }
}

본격적인 콘텐츠 만들기


그럼 이제 "We are ready"에서 본격적인 컨텐츠로 나아가야 할 때다.
우리는 먼저 타이틀만 스크린에 전부 보여주도록 할 것이다.

+) 그 전에 하나 발견한 것이 있는데, yts홈페이지의 API메뉴를 보면 이런 것이 있다.
니꼬를 따라해보니 대충 알겠다. url의 끄트머리에 아래같은 파라미터를 추가해서 페이지를 다양하게 볼 수 있도록 하는 옵션인 듯하다.

우리는 sort_by라는 파라미터로 선택한 사람이 많은 순서대로 정렬하는 파라미터를 선택해 아래와 같이 붙여주었다.
https://yts.mx/api/v2/list_movies.json?sort_by=rating

바뀐 주소를 다시 axios.get("https://yts.mx/api/v2/list_movies.json?sort_by=rating")에 넣어줬다.


자식 컴포넌트 Movie

자, Movies.js를 만들고 새로운 컴포넌트를 만들자.
state가 필요없다면 굳이 클래스형일 이유가 없으므로 함수형으로 만들었다.

function Movie(){
	return <h1> </h1>
}

이렇게 JSX를 만들고

json에서 props로 가져올만한 것들을 살펴본다.

자세히 보면 id, url, title, year등이 있다.

function Movie({id, year, title, summary, poster}){ //parameter에도 브라켓 씌우는거 잊지말자
	return <h4>{title}</h4>;
}

Movie.propTypes ={
	id: PropTypes.number.isRequired,
	year: PropTypes.number.isRequired,
	title: PropTypes.string.isRequired,
	summary: PropTypes.string.isRequired,
	poster: PropTypes.string.isRequired
};
// 각각 프롭타입을 매겨준다.

매개변수에는 혹시나 모를 많은 준비물을 바리바리 싸가고(...)
당장 돔에 넣을 title만 쓰는 모습이다.

그 다음 export default Movie; 하면 Movie 컴포넌트는 끝!
이제 이걸 부모 컴포넌트인 App으로 데려간다.

import React from "react";
import PropTypes from "prop-types";

function Movie({id, year, title, summary, poster}){
	return <h4>{title}</h4>;
}

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

export default Movie;

부모 컴포넌트 App

  1. App에 Movie를 import!
    import Movie from "./Movie";
    🤔.js를 굳이 안붙여도 되나보다?

  2. render()에 집어넣는다.

  render(){
    const {isLoading, movies} = this.state;
    return(
    <div>
      {isLoading ? "Loading..." : movies.map(movie =>(
       //if문의 축약형인 삼항조건연산자.
       //처음 안 것: {}를 지우고 ()로 대신하면, return을 안써도 된다는 점
        <Movie
          key={movie.id} //function Movie(param)에 key 없었는데, 여기서 넣어도 되나봄
          id={movie.id} //prop의 값을 movies를 이용해 채워준다.
          year={movie.year}
          title={movie.title}
          summary={movie.summary}
          poster={movie.medium_cover_image}
        />
      //
      ))}
    </div>
    ) 
  }

movies를 콘솔로그했던 것이 기억이 나는지 모르겠다. movies.data.data."movies" 말이다. movies를 불러와 의 props 내부의 값을 채워주고 있는 모습이다.


import React from 'react';
import axios from "axios";
import Movie from "./Movie";

class App extends React.Component{
  state = {
    isLoading: true,
    movies: []
  };
  getMovies = async() =>{
  const {data:{data:{movies}}} = await axios.get("https://yts.mx/api/v2/list_movies.json?sort_by=rating");
  this.setState({movies, isLoading: false});
}
  componentDidMount(){
    this.getMovies();
  }
  render(){
    const {isLoading, movies} = this.state;
    return(
    <div>
      {isLoading ? "Loading..." : movies.map(movie =>(
        <Movie
          key={movie.id}
          id={movie.id}
          year={movie.year}
          title={movie.title}
          summary={movie.summary}
          poster={movie.medium_cover_image}
        />
      ))}
    </div>
    ) 
  }
}

export default App;

  • 아직까지 확 와닿지는 않아서 부모 컴포넌트와 자녀 컴포넌트 간의 기묘한 공생관계처럼 느껴진다. 개념을 더 명확하게 이해하면 관계도 분명하게 깨달을 수 있을 것 같다.
  • 아직 this가 어렵다.
  • props와 state의 차이에 대해 더 알아봐야..
  • {}를 없애고 ()를 넣으면 return이 내포되어 있어 적지 않아도 된다.
  • 함수형 컴포넌트의 파라미터에 { } 씌우는 것 잊지말자.
  • function Movie(parameter)에 key 없었는데, 부모 컴포넌트에서 render할 때 넣어도 되나보다.
profile
나 미대 나온 개발자야~

0개의 댓글