#7.3 ~ 7.10
지금까지 배운 것들을 응용해서 영화정보를 보여주는 웹 서비스를 만들어 볼거임.
일단 많은 영화정보들을 받을 수 있는 API를 가져오자!
import { useEffect, useState } from 'react';
function App() {
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`https://yts.mx/api/v2/list_movies.json?minimum_rating=9&sort_by=year`)
.then((response) => response.json())
.then((json) => console.log(json));
}, []);
return <div>{loading ? <h1>Loading...</h1> : null}</div>;
}
export default App;
useState
를 사용해 기본값을 true로 줌.return <div>{loading ? <h1>Loading...</h1> : null}</div>;
useEffect(() => {}, []);
빈배열을 주면 처음 페이지가 로딩되었을 때만 코드가 실행됨.useEffect
에 fetch를 넣어 API를 받아옴.function App() {
const [loading, setLoading] = useState(true);
const [movies, setMovies] = useState([]);
useEffect(() => {
fetch(`https://yts.mx/api/v2/list_movies.json?minimum_rating=9&sort_by=year`)
.then((response) => response.json())
.then((json) => {
setMovies(json.data.movies);//변경함수에 fetch 데이터를 넣어줌
setLoading(false); //데이터를 받아 온 후에는 로딩이 끝났기 때문에 false로 바꿔야함
});
}, []);
console.log(movies);
return <div>{loading ? <h1>Loading...</h1> : null}</div>;
}
function App() {
const [loading, setLoading] = useState(true);
const [movies, setMovies] = useState([]);
const getMovies = async () => {
const response = await fetch(`https://yts.mx/api/v2/list_movies.json?minimum_rating=9&sort_by=year`);
const json = await response.json();
setMovies(json.data.movies);
setLoading(false);
};
useEffect(() => {
getMovies();
}, []);
return <div>{loading ? <h1>Loading...</h1> : null}</div>;
}
function App() {
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=9&sort_by=year`)).json();
setMovies(json.data.movies);
setLoading(false);
};
useEffect(() => {
getMovies();
}, []);
console.log(movies);
return <div>{loading ? <h1>Loading...</h1> : null}</div>;
}
map함수를 이용해 화면에 출력하자!
function App() {
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=9&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>
);
}
movie.title
이번엔 리액트앱에서 페이지를 전환하기 위한 방법을 배워볼거임.
App.js
파일안의 화면을 출력하는 코드를 그대로 가져와서 Movie.js
파일을 생성해서 옮기자!
//App.js
import { useEffect, useState } from 'react';
import Movie from './Movie';
function App() {
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=9&sort_by=year`)).json();
setMovies(json.data.movies);
setLoading(false);
};
useEffect(() => {
getMovies();
}, []);
return (
<div>
{loading ? (
<h1>Loading...</h1>
) : (
<div>
{movies.map((movie) => (
<Movie
key={movie.id}
coverImg={movie.medium_cover_image}
title={movie.title}
summary={movie.summary}
genres={movie.genres}
/>
))}
</div>
)}
</div>
);
}
App.js
에 Movie.js
를 import 해줌.<Movie/>
컴포넌트에 props로 속성을 보내줘야함//Movie.js
import PropTypes from "prop-types";
function Movie({ coverImg, title, summary, genres }) {
return (
<div>
<img src={coverImg} alt={title} />
<h2>{title}</h2>
<p>{summary}</p>
<ul>
{genres.map((g) => (
<li key={g}>{g}</li>
))}
</ul>
</div>
);
}
Movie.propTypes = { //PropTypes이라고해서 에러났음. propTypes라고 쓰기 (소문자로!)
coverImg: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
summary: PropTypes.string.isRequired,
genres: PropTypes.arrayOf(PropTypes.string).isRequired,
};
export default Movie;
{ coverImg, title, summary, genres }
App.js
에서 props로 받아옴.<img src={coverImg} alt={title} />
img
엘리먼트들은 alt 속성을 가지기 때문 (그냥 alt를 갖는게 더 좋아서 알려주는것)PropTypes
를 사용하자npm i prop-types
로 설치이제 React Router에 대해 배워보자! React Router는 페이지를 전환하는 거임.
일단 npm i react-router-dom@5.3.0
로 설치하자
(현재는 react-router-dom 6버전을 쓰지만 이 강의(2021)에서는 react-router-dom을 5.3.0버전을 씀. 문법이 다르니 참고하기)
components
라는 폴더를 생성해 주고 기존의 Movie.js
를 옮겨줌 (다양한 컴포넌트들을 모아놓는 폴더)routes
라는 폴더를 생성해 주고 Detail.js
와 Home.js
파일 만들어줌 (url마다 다른 페이지를 보여주는 용도)function App() {
return null;
}
export default App;
import { useState, useEffect } from "react";
import Movie from "../components/Movie";
function Home() {
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=9&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) => (
<Movie
key={movie.id}
coverImg={movie.medium_cover_image}
title={movie.title}
summary={movie.summary}
genres={movie.genres}
/>
))}
</div>
)}
</div>
);
}
export default Home;
App.js
를 Home.js
로 옮겨옴function Detail() {
return <h1>Detail</h1>;
}
export default Detail;
react-route-dom을 사용해보자!
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import Home from "./routes/Home";
import Detail from "./routes/Detail";
//컴포넌트 import 꼭 해오기
function App() {
return (
<Router>
<Switch>
<Route path="/movie">
<Detail />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</Router>
);
}
export default App;
/movie
path에 있다면 Detail 컴포넌트를 보여줄거임./
path에 있다면 Home 컴포넌트를 보여줄거임. <h2> <a href="/movie">{title}</a></h2>
이런식으로 하면 페이지 전체가 다 로딩되기 때문이다.
//Movie.js
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
function Movie({ coverImg, title, summary, genres }) {
return (
<div>
<img src={coverImg} alt={title} />
<h2>
<Link to="/movie">{title}</Link>
</h2>
<p>{summary}</p>
<ul>
{genres.map((g) => (
<li key={g}>{g}</li>
))}
</ul>
</div>
);
}
Movie.propTypes = { //PropTypes이라고 하니까 에러났음 propTypes로 바꾸면됨
coverImg: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
summary: PropTypes.string.isRequired,
genres: PropTypes.arrayOf(PropTypes.string).isRequired,
};
export default Movie;
-제목을 누르면 /movie
페이지로 가는걸 볼 수있음.
⭐️추가: 강의의 댓글들을 보니 지금은 react-router-dom 5버전의 Switch 문법보다는 최신 6버전 문법을 많이 사용하는것 같았다. 그래서 6버전으로도 바꿔보자!
일단 npm install react-router-dom@6.3.0
6버전으로 설치하고 아래와 같이 작성하면됨
//App.js
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./routes/Home";
import Detail from "./routes/Detail";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/movie" element={<Detail />} />
</Routes>
</BrowserRouter>
);
}
export default App;
공식문서를 참고하자!
//Movie.js
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
function Movie({ coverImg, title, summary, genres }) {
return (
<div>
<img src={coverImg} alt={title} />
<h2>
<Link to="/movie">{title}</Link>
</h2>
<p>{summary}</p>
<ul>
{genres.map((g) => (
<li key={g}>{g}</li>
))}
</ul>
</div>
);
}
Movie.propTypes = { //PropTypes이라고 하니까 에러났음 propTypes로 쓰기
coverImg: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
summary: PropTypes.string.isRequired,
genres: PropTypes.arrayOf(PropTypes.string).isRequired,
};
export default Movie;
Link
는 똑같은 문법을 써서 안고쳐도 된다.리액트 Router는 다이나믹(동적) url을 지원해줌
다이나믹하다는 건 url에 변수를 넣을 수 있다는 의미임.
-위에처럼 id 변수를 받아오게 만들거임.
:id
를 작성해줌<Detail />
페이지를 보여줄거임<Movie/>
컴포넌트에 id값이 있어야 하는데 받아오는 props중에 id가 없으므로 부모 요소인Home
에서 id를 props로 가져오자!Home
-> <Movie/>
컴포넌트로 props로 id를 넘겨주는 코드를 작성하고id
를 받아 Link
태그에 넣어줌파라미터에 오는 id값이 뭔지 알아내야 하는데 어떻게 알아낼까?
💡 useParams함수를 사용하면 됨!
import { useParams } from 'react-router-dom';
function Detail() {
const x = useParams()
console.log(x);
return <h1>Detail</h1>;
}
export default Detail;
useParams()
: 리액트 라우터에서 제공하는 url에 변경되는 값을 반환해주는 함수<Route path="/movie/:id" element={<Detail />} />
의 :id 값을 반환해준거임import { useEffect } from "react";
import { useParams } from "react-router-dom";
function Detail() {
const { id } = useParams();
const getMovie = async () => {
const json = await (
await fetch(`https://yts.mx/api/v2/movie_details.json?movie_id=${id}`)
).json();
console.log(json);
};
useEffect(() => {
getMovie();
}, []);
return <h1>Detail</h1>;
}
export default Detail;