MapleStory Finger Point
본문 바로가기
Front-end/React.Js

[nomad coder] 리액트 기초 7 - 총정리

by 디팔⸜( ◜࿁◝ )⸝︎︎ 2022. 11. 26.

- 현재 리액트 프로젝트를 진행한 폴더의 구성이다.

- 영화를 불러오고 펼쳐주는 기능을 하는 코드를 컴포넌트로 따로 구분하였으며

- 라우터 기능을 이용하기 위해 메인화면(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 패키지를 통해 배포하였다.

package.json 안에서의 세팅

 

script에서 deploy, predeploy를 설정해줘야 한다.

- predeploy를 지정하면, deploy를 실행하기만 해도 그 전에 predeploy를 실행한다. (pre라고 붙으면 그렇게 되나?)

- 웹 배포를 하기 전에, build라는 과정을 통해 웹 브라우저가 이해할 수 있는 모습으로 코드를 변경시키고

   그를 깃헙 페이지스에 올린다는 개념같다.

 

 

설명이 잘 되어있어 긁어와본 자료! 이거 참고하면 더욱 수월하게 배포할 수 있을 것이다!

 

gh-pages로 내 React 웹사이트 배포하기

GitHub 레포지토리의 React 프로젝트를 무료로 배포하는 방법을 알아봅시다 !

velog.io


그리하여 리액트 기초를 연습해본 페이지. 다른 기능들, 외적인 부분을 꾸밀 시간이 있었다면 좋았겠다고 생각한다 ^_^

https://beegoat.github.io/react-practice

 

useState, useEffect, Router등 많은 기능을 사용해보면서 익히게 된 유익한 시간!

nomad coder는 선한 영향력을 많이 끼치는 것 같다! 감사합니다! 떼꿰로 '-^

댓글