다른 state에서 id 가져오기 - useParams()

이윤희·2025년 1월 5일

React/Next 일기

목록 보기
11/52

배경

state에 들어있는 상품의 id를 상세 페이지에서 사용하고 싶음

근데 그러려면 그게 몇 번째 상품인지를 알아야 하는데, 내가 반복문을 사용하지 않아서 i 를 전해줄 방법을 모르겠다.

data.js의 데이터는 배열로 되어 있기 때문에 먼저 배열의 몇번째 요소에 접근해야 뒤에 요소를 선택할 수 있다. 그 몇 번째 요소를 어떻게하면 선택할 수 있는지 도저히 모르겠어서 GPT한테 물어봤다. URL파라미터를 이용하면 되는 건가?

GPT

좋은 질문입니다! 😊 URL 파라미터(params)를 활용하면 원하는 데이터를 정확히 식별할 수 있습니다. 지금처럼 data.js에 있는 상품 데이터를 id 값을 기준으로 상세 페이지에서 사용하는 방법을 차근차근 설명드리겠습니다.


1. URL 파라미터로 데이터를 식별하는 방법

/detail/:id라는 라우팅 경로를 사용하고 있으니, URL에 포함된 :id 값을 이용해 해당 상품이 몇 번째 요소인지 찾아낼 수 있습니다. React Router는 useParams()라는 훅을 제공해 URL 파라미터를 쉽게 가져올 수 있습니다.

현재 URL이 /detail/1이라면:

  • useParams()를 사용하면 id 값을 가져올 수 있습니다.
  • id 값을 활용해 data.js 배열에서 해당하는 상품 데이터를 찾을 수 있습니다.

2. 구현하기

2.1 Detail.js 수정

React Router의 useParams 훅을 사용하여 URL 파라미터를 가져옵니다. 그런 다음 props.shoes 배열에서 해당 상품의 데이터를 찾으면 됩니다.

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

function Detail(props) {
  // URL의 :id 값을 가져옴
  let { id } = useParams();

  // props.shoes 배열에서 해당 id에 해당하는 상품 찾기
  let foundProduct = props.shoes.find((product) => product.id === parseInt(id));

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

export default Detail;

주요 변경점:

  1. useParams()로 URL 파라미터 가져오기

    • useParams()는 현재 URL에서 :id와 같은 파라미터 값을 객체로 반환합니다. 예를 들어, URL이 /detail/1이라면 { id: "1" }을 반환합니다.
    • 이 값은 문자열 형태로 반환되므로 parseInt()를 사용해 숫자로 변환해야 합니다.
  2. props.shoes 배열에서 상품 찾기

    • Array.find() 메서드를 사용하여 props.shoes 배열에서 id 값이 일치하는 상품을 찾습니다.
    • find()는 조건을 만족하는 첫 번째 요소를 반환합니다.
  3. 찾은 상품 데이터 사용하기

    • 찾은 상품 데이터를 foundProduct라는 변수에 저장하고, JSX에서 이를 사용해 상세 정보를 렌더링합니다.

3. App.js 라우터 확인

라우터에서 Detail 컴포넌트를 렌더링하는 부분도 확인해야 합니다. element 속성에는 컴포넌트를 JSX 형태로 전달해야 합니다.

<Route path="/detail/:id" element={<Detail shoes={shoes} />} />

여기서 shoes라는 데이터를 Detail 컴포넌트에 props로 전달하고 있으므로, Detail에서 이 데이터를 사용할 수 있습니다.


4. 결과 확인

  1. /detail/0 URL에 접속하면 id0으로 전달되고, props.shoes 배열에서 id: 0인 상품이 렌더링됩니다.
  2. /detail/1 URL에 접속하면 id1로 전달되고, props.shoes 배열에서 id: 1인 상품이 렌더링됩니다.
  3. /detail/2도 동일하게 작동합니다.

5. 주의할 점

  1. 상품이 없는 경우 처리

    • URL에 잘못된 id 값(예: /detail/100)이 들어온 경우, 배열에서 해당 상품을 찾을 수 없습니다. 이럴 때는 foundProductundefined가 되므로 에러가 발생할 수 있습니다.
    • 이런 상황을 방지하려면 foundProduct가 없는 경우를 처리해 주세요:
      if (!foundProduct) {
        return <div>상품을 찾을 수 없습니다.</div>;
      }
  2. URL 파라미터 값은 문자열

    • useParams()로 가져온 값은 항상 문자열입니다. 따라서 숫자와 비교하려면 parseInt()로 변환해야 합니다.
  3. 데이터 구조 확인

    • props.shoes 배열에 id, title, content, price와 같은 데이터가 있어야 제대로 작동합니다. 데이터 구조가 바뀌면 코드도 수정해야 합니다.

6. 요약

  • React Router의 useParams()를 사용하면 URL의 파라미터 값을 가져올 수 있습니다.
  • Array.find()를 이용해 props.shoes 배열에서 id가 일치하는 상품을 찾습니다.
  • 이렇게 찾은 데이터를 상세 페이지에 표시하면 됩니다.

위 코드대로 진행하시면 원하는 기능을 구현할 수 있을 거예요! 😊


왜 useParams()를 이용해 id값을 가져오고, 그것으로 data.js의 상품 데이터를 찾을 수 있는거죠?
만약에 제가 상품을 정렬해서 상품의 id 가 달라진다면 어떻게 하나요?

좋은 질문이에요! 😊 useParams()를 통해 id 값을 가져오고, 이를 이용해 data.js의 상품 데이터를 찾는 이유와 과정, 그리고 데이터 정렬 시 발생할 수 있는 문제를 차근차근 설명드리겠습니다.


1. useParams()란?

React Router의 useParams() 훅은 URL에 포함된 동적 파라미터 값을 가져오는 데 사용됩니다.

예시:

만약, 라우팅 경로를 /detail/:id로 설정했다면:

  • :id는 동적 파라미터입니다.
  • /detail/0으로 접근하면 id = "0"이 됩니다.
  • /detail/1로 접근하면 id = "1"이 됩니다.

즉, useParams()를 호출하면 현재 URL에서 동적 파라미터를 객체로 반환합니다.

코드로 살펴보기:

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

function Detail() {
  let { id } = useParams(); // URL에서 id를 가져옴
  console.log(id); // URL이 /detail/1이면 id = "1"
}

2. data.js의 상품 데이터를 찾는 원리

데이터의 구조:

data.js 파일의 데이터는 배열로 저장되어 있습니다.

let data = [
  { id: 0, title: "White and Black", content: "Born in France", price: 120000 },
  { id: 1, title: "Red Knit", content: "Born in Seoul", price: 110000 },
  { id: 2, title: "Grey Yordan", content: "Born in the States", price: 130000 },
];

여기서 각 상품의 id 값은 고유한 식별자입니다.

find()를 이용한 데이터 탐색:

URL에서 가져온 id 값을 배열의 각 요소와 비교해 원하는 데이터를 찾습니다. 이 과정에서 Array.find() 메서드를 사용합니다.

let foundProduct = data.find((product) => product.id === parseInt(id));
  • find()는 배열의 각 요소를 순회하며 조건(product.id === parseInt(id))을 만족하는 첫 번째 요소를 반환합니다.
  • parseInt(id)를 사용하는 이유는 useParams()가 문자열로 반환하기 때문에, 숫자와 비교하려면 변환이 필요하기 때문입니다.

3. 정렬 시 문제점과 해결 방법

3.1 문제: 상품 정렬로 인해 id와 배열의 순서가 달라지는 경우

id 값은 고유한 식별자입니다. 만약 데이터를 정렬하거나 순서를 변경하더라도, 각 상품의 id 값은 변하지 않습니다. 따라서 정렬된 상태에서도 id를 기준으로 상품을 정확히 찾아낼 수 있습니다.

예시:

let data = [
  { id: 2, title: "Grey Yordan", content: "Born in the States", price: 130000 },
  { id: 0, title: "White and Black", content: "Born in France", price: 120000 },
  { id: 1, title: "Red Knit", content: "Born in Seoul", price: 110000 },
];

// 정렬된 상태에서도 id 값은 유지됨
let foundProduct = data.find((product) => product.id === 1);
console.log(foundProduct);
// 결과: { id: 1, title: "Red Knit", content: "Born in Seoul", price: 110000 }

3.2 문제: 만약 정렬로 인해 id 자체를 변경했다면?

만약 정렬 후 id 값도 변경되거나, id가 배열의 인덱스와 동일하도록 바꿨다면 문제가 생깁니다. 이 경우, 기존 방식으로 데이터를 찾을 수 없습니다.

해결 방법:

정렬로 인해 id 값이 변경된다면:
1. URL 파라미터로 배열의 인덱스를 전달하기:

  • /detail/:index와 같이 경로를 설정합니다.

  • URL에 배열의 인덱스를 포함하고, 해당 인덱스로 배열의 데이터를 가져옵니다.

    <Route path="/detail/:index" element={<Detail shoes={shoes} />} />
    import { useParams } from "react-router-dom";
    
    function Detail(props) {
      let { index } = useParams();
      let product = props.shoes[parseInt(index)];
      console.log(product); // 배열의 인덱스를 사용해 데이터 찾기
    }
  1. 정렬 후에도 id를 유지하기:
    • 데이터를 정렬해도 id 값은 고유 식별자로 유지되어야 합니다. 데이터를 정렬할 때 id 값을 변경하지 않도록 주의하세요.

4. 데이터 정렬과 유지 방법

데이터를 정렬하면서도 고유한 id를 유지하려면, 정렬은 데이터의 순서를 바꾸는 작업일 뿐, id 값을 변경하지 않으면 됩니다.

예시:

상품 데이터를 가격 순으로 정렬:

let sortedData = [...data].sort((a, b) => a.price - b.price);

정렬된 배열:

[
  { id: 1, title: "Red Knit", content: "Born in Seoul", price: 110000 },
  { id: 0, title: "White and Black", content: "Born in France", price: 120000 },
  { id: 2, title: "Grey Yordan", content: "Born in the States", price: 130000 },
]

id 값은 그대로 유지되므로, URL 파라미터를 활용한 탐색에 문제가 없습니다.


5. 최종 요약

  1. useParams()는 URL의 동적 파라미터 값을 가져오는 데 사용됩니다.
    • 예: /detail/1id = "1"
  2. 배열의 데이터를 고유한 id로 찾으려면 Array.find()를 사용합니다.
  3. 정렬로 인해 데이터 순서가 바뀌더라도, 고유한 id 값이 변하지 않으면 데이터를 찾는 데 문제가 없습니다.
  4. 만약 정렬 후 id가 변경된다면, 배열의 인덱스를 URL 파라미터로 전달하는 방식으로 해결할 수 있습니다.

이 방식으로 하면 상품 데이터를 효율적으로 관리하고, 상세 페이지에서도 원하는 상품 정보를 쉽게 찾을 수 있습니다. 😊

0개의 댓글