- 현재 리액트 프로젝트를 진행한 폴더의 구성이다.
- 영화를 불러오고 펼쳐주는 기능을 하는 코드를 컴포넌트로 따로 구분하였으며
- 라우터 기능을 이용하기 위해 메인화면(Home), 그리고 영화 상세정보(Detail) 화면을 구성하였다.
- App.js에서 라우터 기능을 이용하여 창전환을 할 것이고,
- Index.js는 이렇게 구성된 App.js를 root아래에 rendering 해줄것이다.
index.js
import React from "react";
import ReactDOM from 'react-dom/client';
import App from "./App";
// import "./styles.css";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<App />
);
App.js
import{
BrowserRouter as Router,
Switch,
Routes,
Route,
Link
} from "react-router-dom";
import Home from "./routes/Home";
import Detail from "./routes/Detail";
function App(){
return (
<Router basename={process.env.PUBLIC_URL}>
<Switch>
<Route path="/movie/:id">
<Detail />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</Router>
)
}
export default App;
- npm install react-router-dom 을 통해 라우터를 설치하였다.
- 사용법은 Router-Switch-Route 순으로 감싸고, Route에 path를 지정하고, 그 아래에는 해당 URI에
접속했을 때 뿌릴 컴포넌트를 선언해준다.
- Router basename.. 이하 구문은 gh-pages를 통한 deploy과정에서 필요한 정보를 찾다가 붙였는데,
- 이에 대한 정확한 이해는 하지 못해 관련 정보를 공부할 필요가 있다.
-"/"는 localhost:3000/ 을 의미한다.
-/movie/:id 는 id를 동적으로 받아서 변경된다.
- react-router-dom 6버전이 되면서 바뀐 부분을 주석으로 작성했다.
react-router-dom 5버전 -> 버전6 바뀐 부분
1. Switch컴포넌트가 Routes컴포넌트로 대체되었습니다. Switch -> Routes
2. Route컴포넌트 사이에 자식 컴포넌트를 넣지 않고, element prop에 자식 컴포넌트를 할당하도록 바뀌었습니다. Route path="/" element={< Home / >}
출처 - https://nomadcoders.co/users/sugar 님의 댓글
/components/Movie.js
import PropTypes from "prop-types"
import { Link } from "react-router-dom"
function Movie({id, medium_cover_image, title, summary, genres}){
return (
<div>
<img src={medium_cover_image} alt={title}/>
<h1>
<Link to={`/movie/${id}`}>{title}</Link>
</h1>
<p>{summary}</p>
<ul>
{genres.map((g) => (
<li key={g}>{g}</li>
))}
</ul>
</div>
)
}
Movie.propTypes = {
id: PropTypes.number.isRequired,
medium_cover_image: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
summary: PropTypes.string.isRequired,
genres: PropTypes.arrayOf(PropTypes.string).isRequired
}
export default Movie
- 부모 컴포넌트로부터 {} 괄호안의 prop들을 받아와서, 해당 데이터를 가공하여 영화 페이지를 그려내는 컴포넌트이다.
- propTypes를 통해, 해당 값들을 검증하는 과정을 거친다.
- 또 주목해야 할 부분은, <h1> 태그로 감싸져있는 {title}을 <a> 태그가 아닌 <Link> 라는 태그로 받고있다.
- 이는 react-router-dom에서 가져온 기능으로, 새로고침을 하지 않고 해당 링크로 이동시켜주는 기능을 한다.
- 백틱으로 감싸서 ${}를 통해 변수를 전달하는 방식으로, 부모로부터 받아온 prop, id를 전달해줘서 해당 URL로 이동하도록 한다.
/routes/Home.js
import { useEffect, useState } 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=8.8&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}
id={movie.id}
medium_cover_image={movie.medium_cover_image}
title={movie.title}
summary={movie.summary}
genres={movie.genres}
/>
))}
</div>
)}
</div>
);
}
export default Home;
- 영화정보를 담고있는 API 를 통해, 해당 정보가 fetch를 통해 들어온다. 이는 async-await 구문으로 동작한다.
- useEffect로 해당 함수는 단 한 번만 실행된다. 즉 API를 로드하는건 처음에 딱 한 번만 실행된다.
- 가져온 값으로 Movie 컴포넌트에 maps함수를 통한 각각의 요소들을 가공하여 전달한다. (부모 -> 자식)
/routes/Detail.js
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { Link } from "react-router-dom";
function Detail(){
const [loading, setLoading] = useState(true);
const [info, setInfo] = useState();
const { id } = useParams();
const getMovie = async () => {
const json = await (
await fetch(`https://yts.mx/api/v2/movie_details.json?movie_id=${id}`)
).json();
setInfo(json.data.movie);
setLoading(false);
};
useEffect(() => {
getMovie();
}, []);
return(
<div>
{loading? (<h1> Loading .... </h1>) :
(
<div>
<img src={info.medium_cover_image} />
<h1>{info.title}</h1>
<span>{info.genres}</span>
<span>{info.rating}</span>
<p>{info.description_full}</p>
<Link to="/">Home</Link>
</div>
)
}
</div>
)
}
export default Detail;
- 상세 페이지로, 여기서 주목해야 할 부분은 useParams이다.
- URL로 들어온 값, localhost:3000/movie/id 값 이런식으로 우리는 Detail 페이지에 접속하게 되는데, 이때 해당 URL 에서
- id 부분을 긁어온다.
- 그리고 해당 값을, fetch 구문 내에서도 지정해주어, 전체 영화 정보가 담긴 API 에서 단 하나의 영화정보만을 불러온다.
- 그리고 해당 정보를 가지고 제목, 장르, 별점, 설명을 해주고 있으며
- Home 버튼을 통해 메인으로 돌아갈 수 있다.
배포
- 도메인이나 서버 없이, github를 통해 해당 페이지를 웹에 띄울 수 있는 gh-pages 패키지를 통해 배포하였다.
- predeploy를 지정하면, deploy를 실행하기만 해도 그 전에 predeploy를 실행한다. (pre라고 붙으면 그렇게 되나?)
- 웹 배포를 하기 전에, build라는 과정을 통해 웹 브라우저가 이해할 수 있는 모습으로 코드를 변경시키고
그를 깃헙 페이지스에 올린다는 개념같다.
설명이 잘 되어있어 긁어와본 자료! 이거 참고하면 더욱 수월하게 배포할 수 있을 것이다!
gh-pages로 내 React 웹사이트 배포하기
GitHub 레포지토리의 React 프로젝트를 무료로 배포하는 방법을 알아봅시다 !
velog.io
그리하여 리액트 기초를 연습해본 페이지. 다른 기능들, 외적인 부분을 꾸밀 시간이 있었다면 좋았겠다고 생각한다 ^_^
https://beegoat.github.io/react-practice
useState, useEffect, Router등 많은 기능을 사용해보면서 익히게 된 유익한 시간!
nomad coder는 선한 영향력을 많이 끼치는 것 같다! 감사합니다! 떼꿰로 '-^
'Front-end > React.Js' 카테고리의 다른 글
[nomad coder] 리액트 기초 5 - API(코인 시세표) (0) | 2022.11.25 |
---|---|
[nomad coder] 리액트 기초 4 - todo list 만들기 (0) | 2022.11.25 |
[nomad coder] 리액트 기초 3 - 번외(Cleanup Function) (0) | 2022.11.24 |
[nomad coder] 리액트 기초 3 (0) | 2022.11.24 |
[nomad coder] 리액트 기초 2 (0) | 2022.11.24 |
댓글