안녕하세요 갈아만든쌀 입니다. 오늘은 React이야기. 맨 아래 깃허브 링크도 추가하였습니다
적용 가능 시나리오
- 상품 디테일 보기
키 컴포넌트
import {Link, useParams} from 'react-router-dom'
흐름 및 주요 부분 설명
dishes.js / comments.js -> MainComponent.js 중 <Route path="/menu/:dishId"~/> -> DishdetailComponent.js
코세라 풀스텍 강의 중 일부입니다.
dishes.js 및 comments.js에는 json형식으로 데이터를 담고 있습니다. 이 데이터를 MainComponent.js에 임포트한 후 state에 담습니다. state에 담긴 위 두 정보를 DishdetailCompont에 통째로 넘깁니다.
이후 DishdetailComponent안에서 dishId에 맞는 정보만 filter합니다
이용할 데이터
export const DISHES =
[
{
id: 0,
name:'Uthappizza',
image: '/assets/images/uthappizza.png',
category: 'mains',
label:'Hot',
price:'4.99',
featured: true,
description:'A unique combination of Indian Uthappam (pancake) and Italian pizza, topped with Cerignola olives, ripe vine cherry tomatoes, Vidalia onion, Guntur chillies and Buffalo Paneer.'
},
{
id: 1,
name:'Zucchipakoda',
image: '/assets/images/zucchipakoda.png',
category: 'appetizer',
label:'',
price:'1.99',
featured: false,
description:'Deep fried Zucchini coated with mildly spiced Chickpea flour batter accompanied with a sweet-tangy tamarind sauce'
},
{
id: 2,
name:'Vadonut',
image: '/assets/images/vadonut.png',
category: 'appetizer',
label:'New',
price:'1.99',
featured: false,
description:'A quintessential ConFusion experience, is it a vada or is it a donut?'
},
{
id: 3,
name:'ElaiCheese Cake',
image: '/assets/images/elaicheesecake.png',
category: 'dessert',
label:'',
price:'2.99',
featured: false,
description:'A delectable, semi-sweet New York Style Cheese Cake, with Graham cracker crust and spiced with Indian cardamoms'
}
];
▶︎ dishes.js
export const COMMENTS =
[
{
id: 0,
dishId: 0,
rating: 5,
comment: "Imagine all the eatables, living in conFusion!",
author: "John Lemon",
date: "2012-10-16T17:57:28.556094Z"
},
{
id: 1,
dishId: 0,
rating: 4,
comment: "Sends anyone to heaven, I wish I could get my mother-in-law to eat it!",
author: "Paul McVites",
date: "2014-09-05T17:57:28.556094Z"
},
{
id: 2,
dishId: 0,
rating: 3,
comment: "Eat it, just eat it!",
author: "Michael Jaikishan",
date: "2015-02-13T17:57:28.556094Z"
},
{
id: 3,
dishId: 0,
rating: 4,
comment: "Ultimate, Reaching for the stars!",
author: "Ringo Starry",
date: "2013-12-02T17:57:28.556094Z"
},
{
id: 4,
dishId: 0,
rating: 2,
comment: "It's your birthday, we're gonna party!",
author: "25 Cent",
date: "2011-12-02T17:57:28.556094Z"
},
{
id: 5,
dishId: 1,
rating: 5,
comment: "Imagine all the eatables, living in conFusion!",
author: "John Lemon",
date: "2012-10-16T17:57:28.556094Z"
},
{
id: 6,
dishId: 1,
rating: 4,
comment: "Sends anyone to heaven, I wish I could get my mother-in-law to eat it!",
author: "Paul McVites",
date: "2014-09-05T17:57:28.556094Z"
},
{
id: 7,
dishId: 1,
rating: 3,
comment: "Eat it, just eat it!",
author: "Michael Jaikishan",
date: "2015-02-13T17:57:28.556094Z"
},
{
id: 8,
dishId: 1,
rating: 4,
comment: "Ultimate, Reaching for the stars!",
author: "Ringo Starry",
date: "2013-12-02T17:57:28.556094Z"
},
{
id: 9,
dishId: 1,
rating: 2,
comment: "It's your birthday, we're gonna party!",
author: "25 Cent",
date: "2011-12-02T17:57:28.556094Z"
},
{
id: 10,
dishId: 2,
rating: 5,
comment: "Imagine all the eatables, living in conFusion!",
author: "John Lemon",
date: "2012-10-16T17:57:28.556094Z"
},
{
id: 11,
dishId: 2,
rating: 4,
comment: "Sends anyone to heaven, I wish I could get my mother-in-law to eat it!",
author: "Paul McVites",
date: "2014-09-05T17:57:28.556094Z"
},
{
id: 12,
dishId: 2,
rating: 3,
comment: "Eat it, just eat it!",
author: "Michael Jaikishan",
date: "2015-02-13T17:57:28.556094Z"
},
{
id: 13,
dishId: 2,
rating: 4,
comment: "Ultimate, Reaching for the stars!",
author: "Ringo Starry",
date: "2013-12-02T17:57:28.556094Z"
},
{
id: 14,
dishId: 2,
rating: 2,
comment: "It's your birthday, we're gonna party!",
author: "25 Cent",
date: "2011-12-02T17:57:28.556094Z"
},
{
id: 15,
dishId: 3,
rating: 5,
comment: "Imagine all the eatables, living in conFusion!",
author: "John Lemon",
date: "2012-10-16T17:57:28.556094Z"
},
{
id: 16,
dishId: 3,
rating: 4,
comment: "Sends anyone to heaven, I wish I could get my mother-in-law to eat it!",
author: "Paul McVites",
date: "2014-09-05T17:57:28.556094Z"
},
{
id: 17,
dishId: 3,
rating: 3,
comment: "Eat it, just eat it!",
author: "Michael Jaikishan",
date: "2015-02-13T17:57:28.556094Z"
},
{
id: 18,
dishId: 3,
rating: 4,
comment: "Ultimate, Reaching for the stars!",
author: "Ringo Starry",
date: "2013-12-02T17:57:28.556094Z"
},
{
id: 19,
dishId: 3,
rating: 2,
comment: "It's your birthday, we're gonna party!",
author: "25 Cent",
date: "2011-12-02T17:57:28.556094Z"
}
]
▶︎ comments.js
State에 데이터 담기
import { COMMENTS } from '../shared/comments';
import { LEADERS } from '../shared/leaders';
import { PROMOTIONS } from '../shared/promotions';
import {DISHES} from '../shared/dishes';
.
.
.
class Main extends Component {
constructor(props){
super(props);
this.state={
dishes: DISHES,
commnets : COMMENTS,
promotions : PROMOTIONS,
leaders : LEADERS
};
}
.
.
.
▶︎ MainComponent.js
데이터를 담은 자바스크립트 파일을 import합니다. 그리고 constructor부분에 위와같이 설정하여 state에 각 값을 넣어줍니다
DishdetailComponent에 넘기기
<div>
<Header />
<Routes>
<Route path="/home" element={<HomePage/>} />
<Route exact path="/menu" element={<Menu dishes={this.state.dishes} />} /> // order matters
<Route path="/menu/:dishId" element={<DishDetail dishes={this.state.dishes} comments={this.state.commnets} />} />
<Route exact path="/aboutus" element={<About leaders={this.state.leaders} />}/>
<Route exact path="/contactus" element={<Contact/>} />
<Route path="*" element={<Navigate to="/home" />}/>
</Routes>
<Footer/>
</div>
▶︎ MainComponent.js. 이중 Route Path="/menu/:dishId" ... 부분을 보면 됩니다
react-router-dom v6에 오면서 switch -> Routes로 바뀌었습니다. 또한 component로 쓰던 부분을 element로 변경하였습니다.
위의 :dishId라고 써있는 부분을 꼭 기억해주세요
dishId값 읽기 및 json array filter
useParams를 import합니다
import {Link, useParams} from 'react-router-dom'
▶︎ DishdetailComponet.js
코드 자체는 크게 별게 없습니다
let {dishId} = useParams();
if(props == null){
return(
<div></div>
);
}
console.log(dishId);
console.log(props);
console.log(props.dishes);
const dish = props.dishes.filter((dish) => dish.id === parseInt(dishId,10))[0];
const comment = props.comments.filter((c) => c.dishId === parseInt(dishId,10));
console.log(dish);
▶︎ DishdetailComponet.js 중 url parameter읽는 부분
아까 /menu/:dishId 라고 쓰신 부분이 기억날겁니다. 이 url 을 받는 위치에선 같은 이름으로 useParams()를 써야 그 값을 읽어올 수 있습니다.
즉,
let{id} = useParams(); -> 안됨
let{dishId} = useParams(); -> 됨
이렇습니다. 해보니 그렇더라고요
아래 filter 부분은 각 array의 id값과 dishId가 동일한지 체크합니다. parseInt부분은 integer 10방식으로 바꾼다라는 뜻이랍니다.