저번에 app.js (메인페이지) 파일에 디테일 컴포넌트를 하나 만들었는데요
<Route path ="/detail" element ={<Detail />}/>
여기에는 상품정보가 아직 채워지지 않은 상태입니다.
그래서 props 를 사용해서 shoes 정보들을 입력해볼게요
<Route path ="/detail" element ={<Detail shoes={shoes}/>}/>
function Detail(props){
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">
<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>
)
}
export default Detail;
이렇게 하면 현재 상세페이지에는 shoes 데이터의 0번째 정보만 보여집니다
3개의 상품이 모두 보이도록 하려면 어떻게 해야할까요?
라우터를 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}/>}/>
하지만, 만약 상품이 100만개라면 어떨까요?
라우터를 100만개 만들수는 없겠죠?? 하하
이럴때는 URL 파라미터라는 문법을 사용합니다
페이지를 여러개 만드려면?
URL 파라미터라는 문법을 써야 한다고 말했습니다
<Route path ="/detail/:id" element ={<Detail shoes={shoes}/>}/>
path 작명할때 /:어쩌구 라고 쓰면
"아무문자"를 뜻합니다.
위의 코드는 주소창에 /detail/아무거나 입력했을때 <Detail> 컴포넌트를 보여달라는 뜻입니다
/detail/0
/detail/1
/detail/2
얘네 모두 <Detail> 컴포넌트 를 보여줍니다
페이지 마다 다른 내용을 보여주고 싶어요
/detail/0
/detail/1
/detail/2
얘네 모두 <Detail> 컴포넌트에서 0번째 상품정보를 보여주고 있습니다
(Detail.js)
<h4 className="pt-5">{props.shoes[현재url에입력된숫자].title}</h4>
<p>{props.shoes[0].content}</p>
<p>{props.shoes[0].price}원</p>
<button className="btn btn-danger">주문하기</button>
원래 0이 있던 자리에 [현재url에입력된숫자]를 가져올겁니다
그럼 /detail/1로 접속하면 1번째 상품명을 보여줄 수 있게요.
어떻게 [현재url에입력된숫자]를 가져오냐고요?
useParams() 라는 함수를 쓰면됩니다
import { useParams } from "react-router-dom";
function Detail(props){
let {id} = useParams(); // id라는 변수에 url파라미터를 남겨줌
return(
<div className="container">
<div className="row">
<div className="col-md-6">
<img src={"https://codingapple1.github.io/shop/shoes"+(Number(id)+1)+".jpg"} width="100%" />
</div>
<div className="col-md-6">
<h4 className="pt-5">{props.shoes[id].title}</h4>
<p>{props.shoes[id].content}</p>
<p>{props.shoes[id].price}원</p>
<button className="btn btn-danger">주문하기</button>
</div>
</div>
</div>
)
}
export default Detail;
원래 [0]이 있던 자리에 [id]를 넣어주었다
참고로 id 그 자체는 Detail.js 에서 선언된 것이기 때문에, 그 자체가 props는 아니다.
shoes 데이터를 props로 불러온 것이지.
그래서 사진의 링크를 수정할때 시행착오가 있었다
<img src={"https://codingapple1.github.io/shop/shoes"+(Number(id)+1)+".jpg"} width="100%" />
요 코드에서 0번째 사진정보는 /shoes1.jpg
1번째 사진정보는 /shoes2.jpg
2번째 사진정보는 /shoes3.jpg
형식으로 표기해주어야 한다.
그래서 id 보다 1을 더해주어야 하는데
id 가 문자열로 인식되는 것 같아서 Number() 를 이용해 숫자로 바꾸어주고 +1을 해주니 사진도 잘 출력이 되었다
주소창에 detail/1 을 입력하니
1번째 상품정보가 모두 잘 입력되었다. (사진, 상품명, 상품설명, 가격, 주문하기 버튼 모두)
응용문제
Q. 자료의 순서가 변경되면 상세페이지도 고장나는 문제는 어떻게 해결할까?
Detail.js에 데이터바인딩할 때 0번째 상품의 제목을 여기 보여주세요~ 라고 썼는데
상품의 영구번호가 0인 상품의 제목을 여기 보여주세요~ 하면 되겠군요.
영구번호는 shoes라는 상품 데이터안에 {id : 0} 이런 식으로 함께 저장되어있습니다
배열을 거를때 쓰는 find() 함수를 찾아보았는데요
find() 함수는 array.find() 는 배열을 순환하면서
콜백함수의 조건에 만족하는 첫번째 배열요소를 반환한다.
만약 조건에 만족하는 요소가 없다면, undefined 를 return 합니다
filter()함수를 적용해보았는데
console.log(찾은상품.title) undefined 로 뜨네요 ㅜㅜ
filter()함수는 결과가 true를 반환한 원소들로만 배열을 만듭니다.
객체가 아닌 배열을 리턴하기 때문에 찾은상품.title으로 입력하면 undefined가 뜨는거죠
function Detail(props){
let {id} = useParams(); // id라는 변수에 url파라미터를 남겨줌
//현재 url에 입력한 번호와 같은 번호를 가진 상품을 찾아서
//let 찾은상품 = props.shoes.filter((x)=> x.id == id);
//console.log(찾은상품)
//console.log(찾은상품.title) undefined
let 찾은상품 = props.shoes.find((x)=> x.id == id);
console.log(찾은상품)
return(
<div className="container">
<div className="row">
<div className="col-md-6">
<img src={"https://codingapple1.github.io/shop/shoes"+(Number(id)+1)+".jpg"} width="100%" />
</div>
<div className="col-md-6">
<h4 className="pt-5">{찾은상품.title}</h4>
<p>{찾은상품.content}</p>
<p>{찾은상품.price}원</p>
<button className="btn btn-danger">주문하기</button>
</div>
</div>
</div>
)
}
export default Detail;
'React' 카테고리의 다른 글
useEffect 사용조건 총정리 (0) | 2023.04.03 |
---|---|
리액트에서 useEffect 사용하는 법 (창 사라지게 만들기) (0) | 2023.04.02 |
상품목록을 컴포넌트로 만들기(map 함수) (0) | 2023.04.01 |
Input (사용자가 입력한 값 다루기) (2) | 2023.03.28 |
props : 자식이 부모의 state 가져다쓰고 싶을 때 (0) | 2023.03.26 |