Dynamic Routes

Dynamic Routes

0. 시작하기 전..

 - 코딩앙마님의 강의를 참고하였습니다! (강의영상 바로가기)

 - 사용된 API

 

1. Dynamic Routes 배우기 전

 - 이젠 api를 통해서 상품을 불러오겠습니다.

 - #1. api 호출을 위해서 VScode 터미널에 npm i axios를 입력하여, 설치해줍니다.

 - #2. 이제 index.js에 다음과 같이 입력합니다.

import Axios from "axios";
import Head from "next/head";
import { useEffect, useState } from "react";
import ItemList from "@/src/component/ItemList";
import styles from "@/styles/Home.module.css";
import { Divider, Header } from "semantic-ui-react";

export default function Home() {
  const [list, setList] = useState([]);

  const API_URL =
    "http://makeup-api.herokuapp.com/api/v1/products.json?brand=maybelline";

  function getData() {
    // 상품을 받아옴
    Axios.get(API_URL).then((res) => {
      console.log(res.data);
      setList(res.data);
    });
  }

  useEffect(() => {
    getData();
  }, []);

  return (
    <div>
      <Head>
        <title>NewBean</title>
      </Head>
      <Header as="h3" style={{ paddingTop: 40 }}>
        베스트 상품
      </Header>
      <Divider />
      <ItemList list={list.slice(0, 9)} />
      <Header as="h3" style={{ paddingTop: 40 }}>
        신상품
      </Header>
      <Divider />
      <ItemList list={list.slice(9)} />
    </div>
  );
}

 

 - #3. component 폴더ItemList.js 파일을 생성 후, 다음과 같이 입력합니다.

import { Grid } from "semantic-ui-react";
import styles from "./ItemList.module.css";

export default function ItemList({ list }) {
  return (
    <div>
      {/* Grid는 시맨틱 UI 리액트에서 불러옴 */}
      <Grid columns={3}>
        <Grid.Row>
          {list.map((item) => (
            <Grid.Column>
              <div className={styles.wrap}>
                <img
                  src={item.image_link}
                  alt={item.name}
                  className={styles.img_item}
                />
                <strong className={styles.tit_item}>{item.name}</strong>
                <span className={styles.txt_info}>
                  {item.category} {item.product_type}
                </span>
                <strong className={styles.num_price}>${item.price}</strong>
              </div>
            </Grid.Column>
          ))}
        </Grid.Row>
      </Grid>
    </div>
  );
}

 

 - #4. component 폴더 ItemList.module.css 파일을 생성한 후, 다음과 같이 입력합니다.

.wrap {
  padding-bottom: 20px;
  text-align: center;
}

.img_item {
  display: block;
  margin: 0 auto;
}

.tit_item {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  width: 160px;
  margin: 10px auto;
}

.txt_info {
  display: block;
  margin-bottom: 10px;
  color: #999;
  text-align: center;
}

.num_price {
  font-size: 17px;
  font-weight: bold;
  color: #00bcd4;
}

 

 - #5. 이제 브라우저에 들어가 localhost:3000을 입력해봅시다.

    → 그럼 다음과 같이 제대로 상품이 출력되는 것을 확인할 수 있습니다.

 

 

2. Dynamic Routes 

 - 이제, Dynamic Routes를 사용하여 상품 ID가 달라도 하나의 페이지로 관리하고, next/link를 이용해 새로고침 없이 페이지 이동을 해봅시다.

 - #1. view 폴더에서 [id].js 파일을 생성한 후, 다음과 같이 입력해줍니다.

import { useRouter } from "next/router";

const Post = () => {
  const router = useRouter();
  const { id } = router.query;

  return <p>Post: {id}</p>;
};

export default Post;

  

 - #2. 그 다음 ItemList.js에 들어가 다음과 같이 입력하여, Link를 추가해줍니다.

    → 브라우저로 가서 상품을 클릭하면, Post: 숫자가 나오는 것을 확인할 수 있습니다.

    → 잊은 것이 있었는데, map안에 있는 Grid.Column 태그 안에 key를 추가해줍니다.

import { Grid } from "semantic-ui-react";
import Link from "next/link";
import styles from "./ItemList.module.css";

export default function ItemList({ list }) {
  return (
    <div>
      {/* Grid는 시맨틱 UI 리액트에서 불러옴 */}
      <Grid columns={3}>
        <Grid.Row>
          {list.map((item) => (
            <Grid.Column key={item.id}>
              <Link href={`/view/${item.id}`}>
                  <div className={styles.wrap}>
                    <img
                      src={item.image_link}
                      alt={item.name}
                      className={styles.img_item}
                    />
                    <strong className={styles.tit_item}>{item.name}</strong>
                    <span className={styles.txt_info}>
                      {item.category} {item.product_type}
                    </span>
                    <strong className={styles.num_price}>${item.price}</strong>
                  </div>
              </Link>
            </Grid.Column>
          ))}
        </Grid.Row>
      </Grid>
    </div>
  );
}

 

 - #3. 이제 상세페이지를 디자인해봅시다. [id].js에 들어가 다음과 같이 입력합니다.

import Axios from "axios";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import Item from "../../src/component/Item";

const Post = () => {
  const router = useRouter();
  const { id } = router.query;

  const [item, setItem] = useState({});

  const API_URL = `http://makeup-api.herokuapp.com/api/v1/products/${id}.json`;

  function getData() {
    Axios.get(API_URL).then((res) => {
      setItem(res.data);
    });
  }

  useEffect(() => {
    if (id && id > 0) {
      getData();
    }
  }, [id]);

  return <Item item={item} />;
};

export default Post;

 

 - #4. component 폴더 안에 Item.js 파일을 생성한 후, 다음과 같이 입력해줍니다.

import { Button, Header } from "semantic-ui-react";
import styles from "./Item.module.css";

export default function Item({ item }) {
  const {
    name,
    image_link,
    price,
    description,
    updated_at,
    category,
    product_type,
    product_link,
  } = item;
  
  return (
    <>
      <div className={styles.wrap}>
        <div className={styles.img_item}>
          <img src={image_link} alt={name} />
        </div>
        <div className={styles.info_item}>
          <strong className={styles.tit_item}>{name}</strong>
          <strong className={styles.num_price}>${price}</strong>
          <span className={styles.txt_info}>
            {category ? `${category}/` : ""}
            {product_type}
          </span>
          <Button color="orange">구매하기</Button>
        </div>
      </div>
      <Header as="h3">Description</Header>
      <p style={{ paddingBottom: 20, fontSize: 18 }}>{description}</p>
    </>
  );
}

 

 - #5. component 폴더 안에 Item.module.css 파일을 생성한 후, 다음과 같이 입력합니다.

.wrap {
  display: flex;
  padding: 40px 0;
  border-bottom: 1px solid #ccc;
}

.img_item {
  flex: 200px 0 0;
}

.img_item img {
  display: block;
}

.info_item {
  flex: 1 0 0;
}

.tit_item {
  display: block;
  font-size: 24px;
  margin-top: 20px;
}

.num_price {
  display: block;
  font-size: 34px;
  margin-top: 20px;
  color: #00bcd4;
}

.txt_info {
  display: block;
  font-size: 24px;
  margin: 20px 0 40px;
}

 

 - #6. 이제 마지막으로 브라우저에 들어가서 확인해봅시다!

    → 상세페이지가 제대로 나타나는 것을 확인할 수 있습니다.

 

3. 정리하며

 - 지금까지 dynamic routers에 대해 알아보았고, 메인 페이지상세 페이지를 작업해 보았습니다. 

 

※ 참고 깃 주소 : https://github.com/NewBean0312/nextjs-study/commit/684f331eae156c4649ed1dc086a06ff55e0f939f

 

api 적용 및 상세페이지 작업 · NewBean0312/nextjs-study@684f331

NewBean0312 committed Dec 11, 2023

github.com

 

'Front-End Study > Next.js' 카테고리의 다른 글

에러 페이지와 환경 변수  (0) 2023.12.13
서버사이드 렌더링  (0) 2023.12.12
페이지 레이아웃 생성  (0) 2023.12.01
Next.js 설치  (0) 2023.12.01
Next.js  (0) 2023.12.01