[React] - 상세 페이지 만들기

오유민·2024년 1월 21일

지난 시간에 배운 Route 태그의 path 속성을 이용하여 상세 페이지를 만들어 보았다.

📌 상세 페이지 여러개 만들기

/* App.js */ 

<Route path='/detail/:id' element={<DetailPage desserts={desserts}/>} />
  • path는 경로를 나타내고 id는 매개변수로, 여기에는 어떠한 값이든 올 수 있다. 이 매개변수는 DetailPage 컴포넌트에서 사용된다.

  • element 부분은 해당 경로에 매칭될 때 렌더링될 컴포넌트를 지정한다. 현재는 DetailPage 컴포넌트가 desserts prop을 받아오고 있다.

/* Detail.js */

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

const DetailPage=(props)=> {

    let {id} = useParams();
    // useParams에서 가져온 id는 문자열 형태이므로 형변환을 해줘야 함
    const imageNum = Number(id) + 1;
    const imageUrl = `${process.env.PUBLIC_URL}/img/col${imageNum}.jpg`;

    return (

        <div className="container">
            <div className="row">
                <div className="col-md-6">
                <img src={imageUrl} width="100%" />
                </div>
                <div className="col-md-6">
                <h4 className="pt-5">{props.desserts[id].title}</h4>
                <p>{props.desserts[id].content}</p>
                <p>{props.desserts[id].price}</p> 
                
                <button className="btn btn-danger">주문하기</button> 
                </div>
            </div>
    
        </div> 
    );
};

export default DetailPage;
  • DetailPages 컴포넌트는 props를 매개변수로 받아서 부모 state인 App.js의 desserts를 쓸 수 있게 되었다.
 let {id} = useParams();
  • useParams는 React Router에서 제공하는 훅 중 하나로, URL 경로에서 동적으로 전달된 매개변수들을 추출할 때 사용된다. 즉, 현재 경로에서 동적인 부분을 추출하여 사용할 수 있다는 것이다.

  • ex) /detail/:id 와 같은 경로에서 id에 해당하는 값을 추출하는 데 사용, /detail/123인 경우, id 값은 '123'+ 위 코드는 객체 분해 문법 사용

❗️desserts 라는 state를 Detail.js에서 만들지 않고 굳이 prop 하는 이유
: 만약 나중에 수정 사항이 생겼을 경우, prop 하지 않으면 두 파일을 모두 수정해야 하기 때문에 번거로워지기 때문

❗️❗️ 위 상황에서 만약 임의의 조작을 통해 자료의 순서가 변경된다면 상세 페이지는 어떻게 될까?
: 현재는 [id] 로 데이터 바인딩이 되어 있기 때문에 자료의 순서가 변경되면 상세 페이지의 내용도 따라서 변경된다. 이를 방지하고 싶다면 각 자료마다 고유의 값을 부여해주고 이를 토대로 데이터바인딩하면 된다.

/* Data.js */

 let data = [
    {
      id : 0,
      title : "strawberry tart",
      content : "Born in France",
      price : 20000
    },
  
    {
      id : 1,
      title : "mini pies",
      content : "Born in Seoul",
      price : 15000
    },
  
    {
      id : 2,
      title : "Creme Brulee",
      content : "Born in the States",
      price : 10000
    }
  ] 

export default data;
  • 현재 우리는 Data.js 파일을 import 하여 쓰고 있으므로 이 파일의 data 객체 배열의 값을 이용할 수 있다. 마침 여기에 자료의 순서대로 id가 0부터 순차적으로 할당되어 있으니 이를 이용하자.
  • 즉, path의 /:id 의 id 값과 위 코드의 id 값이 같은 것끼리 데이터 바인딩하면 된다는 뜻! => js의 find()를 사용하자
import React from "react";
import { useParams } from "react-router-dom";


const DetailPage=(props)=> {

    let {id} = useParams();
    // useParams에서 가져온 id는 문자열 형태이므로 형변환을 해줘야 함
    const imageNum = Number(id) + 1;
    const imageUrl = `${process.env.PUBLIC_URL}/img/col${imageNum}.jpg`;

    // id와 일치하는 desserts 배열의 요소를 찾아서 productId 변수에 할당
    let productId = props.desserts.find(element => element.id == id)

    return (

        <div className="container">
            <div className="row">
                <div className="col-md-6">
                <img src={imageUrl} width="100%" />
                </div>
                <div className="col-md-6">
                <h4 className="pt-5">{productId.title}</h4>
                <p>{productId.content}</p>
                <p>{productId.price}</p>
                <button className="btn btn-danger">주문하기</button> 
                </div>
            </div>
    
        </div> 
    );
};

export default DetailPage;

let productId = props.desserts.find(element => element.id == id)
  • id와 일치하는 desserts 배열의 요소를 찾아서 productId 변수에 할당해준다.
 <h4 className="pt-5">{productId.title}</h4>
                <p>{productId.content}</p>
                <p>{productId.price}</p>
  • 배열의 인덱스를 사용하는 방법 대신 위 코드처럼 수정해주면 된다.



완성!

profile
개발자연습생의 개발 일기

0개의 댓글