(React API 프로젝트) React Router Dom(HomeCoin+DetailCoin+HomeCoinInfo)

IRISH·2024년 5월 28일
post-thumbnail

실습 목적

  • 라우터를 통해 화면을 관리한다.

설계

  • 기존의 App.js와 App.module.css 의 내용을 각각 src/routes/HomeCoin.js와 src/routes/HomCoin.module.css 파일에 옮긴다.
    • 즉, HomeCoin.js에 API를 통해 fetch 받은 여러 Coin의 정보를 보여준다.
  • src에 components 디렉토리를 만들고, HomeCoin.js에 보일 각 Coin의 정보를 개별로 보여줄 HomeCoinInfo.js를 생성한다.
    • HomeCoinInfo.js를 통해 각 Div의 정보를 갖고 있는다.
    • 특정 Coin의 id에 Link를 건다.
      • 이 Link를 클릭하면, 상세 페이지(src/routes/DetailCoin.js)를 실행한다.
  • DetailCoin에서 각 Coin의 상세 정보를 보여준다.

코드

scr/components/HomeCoinInfo.js

import PropTypes from "prop-types";
import { Link } from "react-router-dom";

function HomeCoinInfo({ rank, id, name, symbol, first_data_at }) {
  return (
    <div>
      <h2>
        <Link to={`/DetailCoin/${id}`}>{id}</Link>
      </h2>
      <ul>
        <li>rank : {rank}</li>
        <li>name : {name}</li>
        <li>symbol : {symbol}</li>
        <li>first_data_at : {first_data_at}</li>
      </ul>
    </div>
  );
}

HomeCoinInfo.propTypes = {
  rank: PropTypes.string.isRequired,
  id: PropTypes.string.isRequired,
  name: PropTypes.string.isRequired,
  symbol: PropTypes.string.isRequired,
  first_data_at: PropTypes.string.isRequired,
};

export default HomeCoinInfo;
  • HomeCoin.js에서 보여지는 다양한 Coin 중 각각의 Coin 정보에 대한 내용이다.
  • coinTracker의 각 coin 정보를 갖는다.
  • propTypes 로 체킹한다.
  • {id} - 코인명에 링크를 걸고, 코인명을 클릭할 경우 Link 태그를 통해 URL을 위와 같은 형식으로 생성

src/routes/HomeCoin.module.css

/* .container {
  height: 100%;
  display: flex;
  justify-content: center;
} */

.coinsMainText {
  text-align: center; /* 텍스트 중앙 정렬 */
}

.coins {
  display: grid;
  grid-template-columns: repeat(4, minmax(400px, 1fr));
  grid-gap: 100px;
  padding: 150px;
  width: 50%;
  padding-top: 20px;
}

.coins > div {
  border: 1px solid #ccc; /* 각 코인 항목에 경계선 추가 */
  padding: 20px; /* 경계선과 내용 사이에 여백 추가 */
  border-radius: 8px; /* 경계선의 모서리를 둥글게 만듦 */
  background-color: #fff; /* 배경색을 흰색으로 설정 */
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 약간의 그림자 추가 */
}

@media screen and (max-width: 1090px) {
  .coins {
    grid-template-columns: 1fr;
    width: 100%;
  }
}

.eachCoin:hover {
  background-color: green;
  transform: scale(1.1); /* 5%만큼 크기를 증가시킴 */
}

src/routes/HomeCoin.js

import React, { useState, useEffect } from "react";
import styles from "./HomeCoin.module.css";
import HomeCoinInfo from "../components/HomeCoinInfo";

function HomeCoin() {
  const [coin, setCoin] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchCoinData() {
      try {
        const response = await fetch("https://api.coinpaprika.com/v1/tickers");
        const coins = await response.json();

        setCoin(coins); // >>> 모두 다 불러옴
      } catch (error) {
        setError(error);
        console.error("Error fetching coin data:", error);
      }
    }

    fetchCoinData();
  }, []);

  if (error) {
    return <div>Error fetching coin data: {error.message}</div>;
  }

  if (!coin) {
    return <div>Loading...</div>;
  }

  return (
    <div className="HomeCoin-js-container">
      <div className={styles.coinsMainText}>
        <h1>IrishNoah Bit-Coin Information</h1>
      </div>

      <div className={styles.coins}>
        {coin.map((data) => (
          <div className={styles.eachCoin}>
            <div>
              <HomeCoinInfo
                rank={data.rank}
                id={data.id}
                name={data.name}
                symbol={data.symbol}
                first_data_at={data.first_data_at}
              />
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

export default HomeCoin;
  • 여러 개의 Coin 정보를 보여준다.
  • map() 함수를 통해 coin 각각의 정보를 HomeCoinInfo에 보낸다.

src/routes/DetailCoin.js

import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";

function DetailCoin() {
  const { id } = useParams(); // URL에서 id 파라미터를 추출합니다.
  const [coin, setCoin] = useState(null);

  useEffect(() => {
    fetch(`https://api.coinpaprika.com/v1/tickers/${id}`) // 코인 정보를 가져오는 API (예시 URL)
      .then((response) => response.json())
      .then((data) => {
        setCoin(data);
        console.log(data);
      })
      .catch((error) => console.error("Error fetching coin data:", error));
  }, [id]); // id가 변경될 때마다 이 effect를 다시 실행합니다.

  if (!coin) {
    return <p>Loading...</p>;
  }

  const quotes = coin.quotes.USD;

  return (
    <div>
      <h1>
        {coin.name} ({coin.id})
      </h1>
      <ul>
        <li>Rank: {coin.rank}</li>
        <li>symbol: {coin.symbol}</li>
        <li>total_supply: {coin.total_supply}</li>
        <li>first_data_at: {coin.first_data_at}</li>
        <li>last_updated: {coin.last_updated}</li>
        {Object.keys(quotes).map((key) => (
          <li key={key}>
            {key}: {quotes[key]}
          </li>
        ))}
      </ul>
    </div>
  );
}

export default DetailCoin;
  • HomeCoin.js에 있는 특정 코인을 클릭할 경우, 해당 코인의 아이디를 파라미터로 보내 https://api.coinpaprika.com/v1/tickers/${id} 와 같이 fetch를 한다.
  • fetch를 통해 받은 정보의 특정 내용들을 보여준다.

src/App.js

import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import DetailCoin from "./routes/DetailCoin";
import HomeCoin from "./routes/HomeCoin";
function App() {
  return (
    <Router>
      <Switch>
        <Route path="/hello">
          <h1>Hello</h1>
        </Route>
        <Route path="/DetailCoin/:id">
          <DetailCoin />
        </Route>
        <Route path="/">
          <HomeCoin />
        </Route>
      </Switch>
    </Router>
  );
}

export default App;
  • 라우터로 각 화면을 제어한다.

src/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 />);

결과 화면

⇒ 화면 1

  • 메인 화면 역할
  • HomeCoin.js 와 동일하며, App.js 에서 HomeCoin.js 는 ‘/’ 로 통제
  • 각 코인의 id에 Link 태그에서 생성한 href가 생성된 것을 알 수 있다.
  • 또한, 각 코인 Div에 보여지는 정보는 HomeCoinInfo.js 를 통해 생성된다.

⇒ 화면 2

  • 위 / 에서 특정 코인의 Link 태그를 선택했을 때 보여지는 각 코인의 Detail 정보이다.
  • 이것은 DetailCoin.js을 통해 보여진다.
profile
#Software Engineer #IRISH

0개의 댓글