[React] react-router3 url파라미터로 상세페이지 이동

qwe8851·2022년 9월 30일
0

💎 React

목록 보기
12/37

특정 component에 urlParams를 사용한 데이터 바인딩으로 동적인 페이지 구현하려고 함
props를 써서 할 수 있겠지만 리엑트 라우터적으로 구현할거임!



(App.js)

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

우선 app.js안에 <Detail>component를 사용하는곳에 shoes라는 props를 전송했다.


(Detail.js)

<div className="container>
  <div className="row">
    <div className="col-md-6">
      <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
    </div>
    <div className="col-md-6 mt-4">
      <h4 className="pt-5">{props.shoes[0].title}</h4>
      <p>{props.shoes[0].content}</p>
      <p>{props.shoes[0].price}</p>
      <button className="btn btn-danger">주문하기</button>
    </div>
  </div> 
</div>

Detail 컴포넌트는 props파라미터를 등록해서 shoes를 사용했음.

근데 props.shoes[0].title을 하면 어떤 주소를 이동해도 다 같은 shoes[0] 상품의 디테일페이지가 나옴

shoes state를 Detail.js안에서 또 만들면 props를 안써도 되지 않나?
→ 나중에 수정이 필요하면 두 군데를 수정해야하므로 이런식으로 하면 안됨.




🤔 상세페이지를 여러개 만들려면?

위에서 만든건 shoes state안에 0번째 상품의 상세페이지임.
상품이 3개면 상세페이지도 3개가 필요함.


<Route path="/detail/0" element={ <Detail shoes={shoes}/> }/>
<Route path="/detail/1" element={ <Detail shoes={shoes}/> }/>
<Route path="/detail/2" element={ <Detail shoes={shoes}/> }/>

<Route>를 3개 만들어도 페이지 3개를 만들 수도 있겠지만 데이터가 많으면 많을수록 실제로 사용이 어려운 코드..


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

그래서 이럴때 쓸 수 있는게 URL 파라미터 문법이다.

path 작명할 때 /:어쩌구~이렇게 사용하면 "아무문자"를 뜻함.

그래서 위에 <Route>는 누군가 주소창에 /detail/아무거나를 입력했을 때 <Detail>컴포넌트를 보여달라는 뜻.

이제그럼
/detail/0
/detail/1
/detail/2
이렇게 접속해도 <Detail> 컴포넌트를 잘 보여줄 수 있음.

/detail/skfjlsjfl...
이런식으로 막 접속해도 <Detail>페이지가 보인다.




🤔 페이지마다 같은 내용을 보여주고 싶지 않다면?

/detail/0
/detail/1
/detail/2
이렇게 여러 페이지를 만들어 놨지만 접속해보면 다 똑같은 0번째 상품만 보여줌.

props.shoes[0]번째를 보여달라고 하드코딩해놨기 때문임.

지금 하드코딩된 자리에 현재 url 파라미터에 입력된 숫자를 넣으면 /detail/1로 접속하면 1번째 상품을 보여줄 수 잇을 듯?


import { useParams } from 'react-router-dom'

function Detail(){
  let {id} = useParams();
  console.log(id)
  
  return (
    <div className="container>
      <div className="row">
        <div className="col-md-6">
          <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
        </div>
        <div className="col-md-6 mt-4">
        <h4 className="pt-5">{props.shoes[id].title}</h4>
        <p>{props.shoes[0].content}</p>
        <p>{props.shoes[0].price}</p>
        <button className="btn btn-danger">주문하기</button>
      </div>
    </div>
  </div>
  )
}

useParams()함수를 쓰면 :/url파라미터자리에 유저가 입력한 값을 가져올 수 있음.

우선 useParams()함수를 상담에 import해오고,
변수에 저장해서 쓰겠음.

위 코드처럼 사용하면
누가 /detail/1로 접속하면 id라는 변수에 1이 들어오고,
누가 /detail/2로 접속하면 id라는 변수에 2이 들어온다.

그래서 props.shoes[id].title을 해주면
페이지마다 각각 다른 상품명을 보여줄 수 있음.

📎참고
path작명 시 url파라미터는 몇 번이고 사용 가능함.
detail/:어쩌구/:저쩌구~..




✨ 응용문제

Q. 자료의 순서가 변경되면 상세페이지도 같이 고장나는 문제는 어떻게 해결할까?

상품순서를 가나다순으로 변경하는 버튼을 만들었다고 가정하면,

이 버튼을 클릭 시 shoes라는 state안에 상품이 가나다순으로 정렬되게 된다.

그럼 원래 0번째 상품이었던 데이터가 후순위로 밀려나게되고, 차순위였던 상품의 데이터가 0번째가 될 수 있는데,
이처럼 상세페이지가 불규칙해지는 문제를 해결해보자!

hint!
Detail.js에 데이터바인딩할 때 0번째 상품의 제목을 보여달라고 코드를 짰는데,
상품의 영구번호가 0인 상품의 제목을 보여달라고 작성하면 될 듯 하다.

그래서 현재 url에 입력한 번화와 같은 번호를 가진 상품을 찾아 데이터 바인딩하면 끝일 듯

.find(), .find() 같은 문법을 찾아보기


A.

(data.js)

[
  {
    id : 0,
    title : "White and Black",
    content : "Born in France",
    price : 120000
  },
  {둘째상품},
  {셋째상품}
] 

data.js파일에 상품정보 데이터들이 들어있는데, 이 안에 id:0이런 영구번호가 있음.

현재 /:id자리에 입력한 값영구번호가 같은 상품을찾아 데이터 바인딩 해주면 해결!

js엔 .find()라는 문법이 있는데 이걸 쓰면 array자료 안에 원하는 항목만 찾아올 수 있다.

array자료.find(()=>{return 조건식});
이런식으로 쓰면 조건식에 맞는 자료를 찾아 return자리에 남겨줌.

(Detail.js)

function Detail(props){

  let { id } = useParams();
  let 찾은상품 = props.shoes.find(function(x){
    return x.id == id
  });

  return (
    <div className="container">
      <div className="row">
        <div className="col-md-6">
          <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
        </div>
        <div className="col-md-6 mt-4">
          <h4 className="pt-5">{찾은상품.title}</h4>
          <p>{zzz.content}</p>
          <p>{찾은상품.price}</p>
          <button className="btn btn-danger">주문하기</button> 
        </div>
      </div>
  </div>  
  )
};

export default Detail;
  1. find()는 array뒤에 붙일 수 있으며 return 조건식을 적으면 조건식에 맞는 자료
  2. find()콜백함수에 파라미터를 넣으면 array자료가 있던 자료를 정함.
  3. x.id -- id라는 조건식으로 array자료.id == url에입력한번호 일 경우 결과를 변수에 담아줌
    그럼 {상품1개}가 남을듯
  4. 마지막으로 {상품1개}를 html에 데이터바인딩 함

더 짧게는
props.shoes.fild((x)=>x.id==id);

  • arrow function에서 return과 중괄호는 동시 생략 가능

🤯 impression

라우터부분은 반복적으로 더 연습해봐야 할 문제같다.
그리고 자바스크립트가 정말 많이 부족하다고 느낀점은
응용문제가 실제로 많이 쓸법한 기초문제 문제였던것 같은데 나한텐 좀 어려웠다..

function도 finde랑 filter를 찾으면서 알게되었는데
유사한 다른 함수들도 많았다.

지하철에서나 자기전에 읽고자기만 해도 도움이 될 듯 하다! 화이팅!

주제엔 조금 어긋나지만 저번 코테에서 봤던 readline! 자바에 scanner와 비슷한 기능인 듯

hook은 강의에서도 너무간단하게 설명해주시고 넘어가셔서 궁금해짐

리덕스도 공부해보기!

profile
FrontEnd Developer with Vue.js, TypeScript

0개의 댓글