비동기적 데이터 페치를 완료했다면 렌더링을 할 차례
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의 개념에 다시 급 혼란이 오기 시작해서 찾아봤다.
짧게 살펴보면
매개변수처럼 컴포넌트에 전달되는 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번의 경우
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")
에 넣어줬다.
자, 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에 Movie를 import!
import Movie from "./Movie";
🤔.js를 굳이 안붙여도 되나보다?
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;