#34. nextJS 동적라우팅 (데이터 생성/가져오기)

박현재·2020년 12월 27일
0
post-thumbnail

동적 라우팅을 빨리 써보고 싶어서 레이아웃 작업이 끝나기 전에 실행해봤어요!!
메인 상품 페이지에서 상품 클릭 시, 해당 상품의 상세정보를 보여줄 때 사용할 수 있습니다.
사용한 프레임워크 및 라이브러리
nextJS, react-hooks, scss, axios

nextJS는 페이지 전환에 최적화되어 있어 상황에 맞는 props를 쓸 수 있습니다. getInitialProps, serverSideProps, staticProps 등 필요에 따라 쓸 수 있는데 자세한 건 다음에 적용하고 공유하겠습니다!
폴더구조는 메인페이지와 상세페이지 2개가 있습니다. 메인페이지에는 해당 index.js파일과 자식컴포넌트인 ItemList파일이 있고, 상세페이지에는 /detail/[id] 파일이 한 개 있습니다. 상세페이지에서 보여주는 내용들은 공용컴포넌트를 자식으로 가져왔습니다.

1. 메인페이지 및 상세페이지에 사용할 목데이터 생성하기

pages의 api폴더안에 목데이터를 만들면 json파일로 가져올 수 있습니다.
/api/getRequestInfo.js

function requestDate() {
  const date = new Date();
  const year = date.getFullYear();
  const month = date.getMonth() + 1;
  const day = date.getDate();
  const hours = date.getHours();
  const minutes = date.getMinutes();
  return (
    `${year}.` +
    `${month < 10 ? 0 + "" + month : month}.` +
    `${day < 10 ? 0 + "" + day : day} ` +
    `${hours < 10 ? 0 + "" + hours : hours}:` +
    `${minutes < 10 ? 0 + "" + minutes : minutes}`
  );
}

const requestInfo = [
  {
    id: 1,
    car_brand: "현카",
    car_type: "부가티 센토디에치",
    car_number: "01가1111",
    phone_number: "+ 82 10 1234 1234",
    location: "서울특별시 강남구",
    date: requestDate(), // 2020.12.25 15:10,
    description: "빠른 처리 부탁드립니다.",
  },
  {
    id: 2,
    car_brand: "동카",
    car_type: "롤스로이스 스웹테일",
    car_number: "02나2222",
    phone_number: "+ 82 10 4321 4321",
    location: "서울특별시 강남구",
    date: requestDate(), // 2020.12.25 15:10,
    description: "안녕하세요.",
  },
  {
    id: 3,
    car_brand: "류카",
    car_type: "파가니 와이라 이몰라",
    car_number: "03다3333",
    phone_number: "+ 82 10 3333 5555",
    location: "서울특별시 강남구",
    date: requestDate(), // 2020.12.25 15:10,
    description: "조심히 오세요.",
  },
  {
    id: 4,
    car_brand: "규카",
    car_type: "부가티 디보",
    car_number: "07라7777",
    phone_number: "+ 82 10 7777 7777",
    location: "서울특별시 강남구",
    date: requestDate(), // 2020.12.25 15:10,
    description: "조심히 오세요.",
  },
  {
    id: 5,
    car_brand: "영카",
    car_type: "마이바흐 엑셀레로",
    car_number: "05마5555",
    phone_number: "+ 82 10 1049 4867",
    location: "서울특별시 강남구",
    date: requestDate(), // 2020.12.25 15:10,
    description: "조심히 오세요.",
  },
  {
    id: 6,
    car_brand: "신카",
    car_type: "부가티 라 부아튀르 누아르",
    car_number: "06바6666",
    phone_number: "+ 82 10 3333 5555",
    location: "서울특별시 강남구",
    date: requestDate(), // 2020.12.25 15:10,
    description: "조심히 오세요.",
  },
];
export default (req, res) => {
  res.statusCode = 200;
  res.json(requestInfo);
}

2. 데이터 가져오기

/index.js

import React, { Fragment, useEffect, useState } from "react";
import ItemList from "./ItemList";
import Axios from "axios";
function ReservationConfirmation() {
  const [list, setList] = useState([]);
  const API = "http://localhost:5700/api/getRequestInfo";

  useEffect(() => {
    Axios.get(API).then((res) => {
      setList(res.data);
    })
  }, []
  );

  return(
  <Fragment>
    <ItemList list={list} />
    </Fragment>)
}
export default ReservationConfirmation;

Axios의 메서드를 이용해서 데이터를 불러오고 자식 컴포넌트인 ItemList에 넘겨줍니다.
/ItemList.js

import React, { Fragment } from "react";
import Link from "next/link";

function ItemList({ list }) {
  console.log(list);
  return (
	<Fragment>
	  <div>
	    {list?.map((info) => {
		return (
		  <div style={{ margin: "50px", textAlign: "center" }} key={info.id}>
		    <Link href={`/user/main/reservation/detail/${info.id}`}>
		      <input type="button" value={"button" + info.id} alt="" />
		    </Link>
		    <div style={{ marginTop: "10px" }} />
		    <div>{info.car_brand}</div>
		    <div style={{ marginTop: "10px" }} />
		    <div>{info.car_type}</div>
		  </div>
	 	);
		})}
	  </div>
	</Fragment>
  );
}
export default ItemList;

여기까지는 데이터를 생성하고 가져오는 과정입니다. 그리고 버튼을 눌렀을 때 상세페이지로 가기 위해서 Link를 import해서 사용했습니다.

3. 동적인 경로 생성

detail폴더를 생성하고 [id].js 파일을 생성해주면 id의 값에 따라서 경로가 생성됩니다.
ex) id===1인 버튼을 클릭했을 때, /detail/1 로 이동하게 됩니다.
/detail/[id].js

import React, { useEffect, useState } from "react";
import { useRouter } from "next/router";
import RequestDetailHeader from "../../../../../components/Header/RequestDetailHeader";
import RequestInfo from "../../../../../components/RequestDetail/RequestInfo";
import ProposalInfo from "../../../../../components/RequestDetail/ProposalInfo";
import Link from "next/link";
import axios from "axios";
import styles from "./ConfirmationDetail.scss";
import {
	DISPATCH_CANCEL,
	DISPATCH_COMPLETE,
} from "../../../../../constants/requestDetail/ProposalInfo";

const API = "http://localhost:5700/api/getRequestInfo";
const isReservation = true;

const ConfirmationDetail = () => {
  const [list, setList] = useState([]);

  useEffect(() => {
    if (id && id > 0) {
      axios.get(API).then((res) => {
        setList(res.data);
      });
    }
  }, [id]);

  return (
    <div className={styles.container}>
      <RequestDetailHeader />
      <div className={styles.menuTab}>
        <Link href="/user/main/reservation/detail">
          <a className={styles.active}>요청상세</a>
        </Link>
        <Link href="/user/main/reservation/detail/chat">
          <a>채팅</a>
        </Link>
      </div>
      <RequestInfo list={list} id={id} />
      <ProposalInfo
        isReservation={isReservation}
        leftButtonValue={DISPATCH_CANCEL}
        rightButtonValue={DISPATCH_COMPLETE}
      />
    </div>
  );
};
export default ConfirmationDetail;

상세페이지 index.js 파일 대신 [id].js 파일을 생성해주면 동적인 경로가 자동으로 지정됩니다.
정말 간단합니다. 로딩페이지의 시간단축 등의 성능개선을 위해서는 serverSideProps 또는 staticProps를 사용할 수 있습니다!

profile
바로 하자, Right Now!

1개의 댓글

comment-user-thumbnail
2020년 12월 27일

올ㅋ

답글 달기