4.0 Fetching Movies from API
fetch
axios
: fetch위에 있는 작은 layer
axios 설치
npm i axios
사용할 API
: YTS-proxy API (by nomad coder)
yts.mx/api/v2/list_movies.json
JsonView - json파일을 예쁘게 보여주는 크롬 확장프로그램
: https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc/related
axios로 가져온 data를 변수에 저장
axios가 우리에게 data를 주지만, 우리는 그 데이터를 잡아야 한다. 그래야 state에 사용 가능.
componentDidMount(){
const movies = axios.get("https://yts.mx/api/v2/list_movies.json");
};
axios는 느릴 수 있다.
따라서, Javascript에게 componentDidMount function이 끝날 때까지 약간 시간이 걸릴 수 있다고 알려야 한다.
이를 위해 componentDidMount 앞에 async를 넣는다.
async componentDidMount(){
const movies = axios.get("https://yts.mx/api/v2/list_movies.json");
};
또는 function을 만든다. (Better react)
getMovies = async () => {
const movies = await axios.get("https://yts.mx/api/v2/list_movies.json");
}
componentDidMount(){
this.getMovies();
};
- asnyc: 이 함수는 비동기(async)이다. "너는 기다려야 함"
- await ___: ___를 기다려야 한다.
+ async가 없다면 await 키워드를 사용할 수 없다!
+ async, await하지 않으면, js는 function을 기다려주지 않을 것이다.
4.1 Rendering the Movies
API에서 읽어온 data에서 movies 뽑아내기
// Not Sexy
const movies = await axios.get("https://yts.mx/api/v2/list_movies.json");
console.log(movies.data.data.movies);
// Sexy -> Do this way
const {data: { data : {movies}}} = await axios.get("https://yts.mx/api/v2/list_movies.json");
console.log(movies);
const {
data: {
data : { movies }
}
} = await axios.get("https://yts.mx/api/v2/list_movies.json");
// this.setState({movies:movies}) // state:axios
// this.setState({ movies }) // summarize
this.setState({ movies, isLoading: false })
- javascript에서 이름이 같은 경우, 단축해서 쓸 수 있다.
- 한 번에 setState 여러 개 가능
movies를 render!
If component가 state가 필요없을 경우:
class component가 될 필요없다. -> function component!
// src/Movie.js
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;
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>
);
}
map은 반드시 무언가 return해줘야 한다!
4.2 Styling the Movies
- css 파일을 import
- HTML element에 style={{}}을 적용
import React from "react";
import axios from "axios";
import Movie from "./Movie";
import "./App.css";
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 (
<section className="container">
{isLoading ? (
<div className="loader">
<span className="loader__text">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}
/>
))}
</div>
)}
</section>
);
}
}
export default App;
import React from "react";
import PropTypes from "prop-types";
import "./Movie.css"
function Movie({ year, title, summary, poster }) {
return (
<div className="movie">
<img src={poster} alt={title} title={title} />
<div className="movie__data">
<h3 className="movie__title">
{title}
</h3>
<h5 className="movie__year">{year}</h5>
<p className="movie__summary">{summary}</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
};
export default Movie;
4.3 Adding Genres
📌 className VS class
HTML에서 class는 class이다.
BUT 이 코드는 JSX이다.javascript class 안에 있으면 component class에 의해 혼란스러워 진다.
따라서, className으로 사용한다.
+ 개발자 도구에서 해당 element를 확인하면, className은 class로 표시된다.
genres는 string의 array형태로 저장되어 있다.
-> map을 사용!
- PropTypes.arrayOf(PropTypes.string)으로 proptypes를 검사
function Movie({ year, title, summary, poster, genres }) {
return (
<div className="movie">
<img src={poster} alt={title} title={title} />
<div className="movie__data">
<h3 className="movie__title">{title}</h3>
<h5 className="movie__year">{year}</h5>
<ul className="genres">
{genres.map((genre, index) => (
<li key={index} className="genres__genre">{genre}</li>
))}
</ul>
<p className="movie__summary">{summary}</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
};
App.js
- genres를 전달
<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>
4.4 Styles Timelapse
그냥 style(css) 적용하는 거 말 1도 안 하고 timelapse로 보여주신 편입니다.
4.5 Cutting the summary
summary의 길이가 모두 다르므로 똑같이 만들기
const summary = "kadflasmvwajepvdaks awjdkv poeqkw;lfcnv apjewklj sdalkjsalmvalsdjwfp";
// summary의 길이
summary.length
// start ~ end 반환
summary.slice(start, end)
// Movie.js에서 적용
<p className="movie__summary">{summary.slice(0, 180)}...</p>
📌 다음 강좌: Cloud에 올려 친구나 가족이 볼 수 있게 하기
'💻 Study > 웹' 카테고리의 다른 글
#6 ROUTING BONUS (0) | 2021.01.10 |
---|---|
#5 CONCLUSIONS (0) | 2021.01.10 |
#3 STATE (0) | 2021.01.10 |
#2 JSX & PROPS (0) | 2021.01.10 |
#1 SETUP (0) | 2021.01.10 |