1. state 변경하기
Redux에서는 object/array 같은 자료형의 state를 직접 수정하는 것이 편리합니다.
Redux에 딸려오는 Immer.js 라이브러리의 도움으로 state 사본을 생성하여 직접 수정해도 잘 작동합니다.
let user = createSlice({
name: 'user',
initialState: { name: 'kim', age: 20 },
reducers: {
changeName(state) {
return { name: 'park', age: 20 };
}
}
});
예를들어 name 값을 kim에서 park으로 바꾸고 싶을 때 위와 같은 코드를 작성해도 되지만,
let user = createSlice({
name : 'user',
initialState : {name : 'kim', age : 20},
reducers : {
changeName(state){
state.name = 'park'
}
}
})
state를 직접 수정해도 잘 변경되는 것을 볼 수 있습니다.
2. 함수 파라미터 활용하기
여러 개의 유사한 기능을 가진 state 변경 함수를 만들도 싶을 때, 파라미터 문법을 사용하여 하나의 함수로 처리할 수 있습니다.
let user = createSlice({
name : 'user',
initialState : {name : 'kim', age : 20},
reducers : {
increase(state){
state.age += 1
}
}
예를 들어, 위의 코드를 사용하면 age가 1씩 증가하는 함수를 만들 수도 있지만,
let user = createSlice({
name: 'user',
initialState: { name: 'kim', age: 20 },
reducers : {
increaseAge(state, action) {
state.age += action.payload;
}
}
});
이렇게 두 번째 파라미터를 사용하여 함수를 만들면, age의 증가량을 지정할 수 있습니다.(두 번째 파라미터는 action을 넣는게 관례입니다.)
action.payload를 사용하면 파라미터에 넣은 자료가 나옵니다.
dispatch(increaseAge(10)); // 나이 +10 증가
dispatch(increaseAge(100)); // 나이 +100 증가
그리고 위와 같이 reducer 함수를 호출하면 increase(10)을 호출하면 나이가 +10 증가하고, increase(100)을 호출하면 나이가 +100 증가합니다.
dispatch 함수를 통해 정의된 reducer 함수들이 실행되어 state가 변경될 수 있습니다.
3. 실습
배운 것을 활용해서 쇼핑몰 사이트를 조금 더 완성시켜보겠습니다.
구현할 기능
1. + 버튼을 누르면 해당 상품의 수량이 1증가한다.
2. 상세페이지 주문하기 버튼을 눌렀을 때, 새로운 상품이 state에 추가된다.
3-1. 수량+1 기능 만들기
(store.js)
let cart = createSlice({
name : 'cart',
initialState : [
{id : 0, name : 'White and Black', count : 2},
{id : 2, name : 'Grey Yordan', count : 1}
],
reducers : {
addCount(state, action){
let 번호 = state.findIndex((a)=>{ return a.id === action.payload })
state[번호].count++
}
}
})
export let { addCount } = cart.actions;
(Cart.js)
import { addCount } from './../store'
<button onClick={()=>{
dispatch(addCount(state.cart[i].id))}}>
+
</button>
1. dispatch() 함수로 상품의 id 값이 payload에 전달됩니다.
(ex. id가 2인 상품의 + 버튼을 누른다 -> 2가 payloda에 전달)
2. findIndex() 함수는 자료를 순회하며 조건식에 대입하고 조건식이 참이면 그게 몇 번째 자료인지 알려줍니다. a는 array 안에 있던 자료가 하나씩 들어갑니다.
(ex. findIndex 함수가 id가 2인 값과 같은지 비교한 후, 1번째 자료이므로 1의 값을 반환한다.)
3. 자료를 1씩 증가시킨다.
(ex. let 번호 = 1 이므로 state[1].count++ 함수가 실행됩니다.)
4. Redux store에 변경된 자료가 반영되고 UI가 업데이트됩니다.
3-2. 주문버튼 누르면 state에 새로운 상품 추가
(store.js)
let cart = createSlice({
name: 'cart',
initialState: [
{ id: 0, name: 'White and Black', count: 2 },
{ id: 2, name: 'Grey Yordan', count: 1 },
],
reducers: {
addCount(state, action) {
let 번호 = state.findIndex((a) => {
return a.id == action.payload;
});
state[번호].count++;
},
addItem(state, action){
let 주문확인 = state.find((item) => item.id === action.payload.id);
if (주문확인) {
주문확인.count++;
} else {
state.push(action.payload);
}
},
},
});
export let { addCount, addItem } = cart.actions;
(Detail.js)
<div className="col-md-6">
<h4 className="pt-5">{찾은상품.title}</h4>
<p>{찾은상품.content}</p>
<p>{찾은상품.price}원</p>
<button className="btn btn-danger" onClick={()=>{
dispatch(addItem({id:찾은상품.id, name:찾은상품.title, count: 1}))
navigate('/cart')
}}>주문하기</button>
</div>
</div>
1. addItem이라는 state를 추가하는 함수를 만듭니다.
2. useNavigate를 import하고 상품 페이지의 주문하기 버튼을 누르면 state에 해당 상품이 추가되고, 장바구니 페이지로 이동합니다.
3. 단, 주문하기 버튼을 눌렀을 때 상품의 id가 이미 배열에 있다면 count만 증가시킵니다.
'React' 카테고리의 다른 글
React 쇼핑몰(localStorage) (1) | 2023.10.29 |
---|---|
React 쇼핑몰(if문 작성 패턴) (1) | 2023.10.28 |
React 쇼핑몰(Redux: state 생성 및 사용) (0) | 2023.10.27 |
React 쇼핑몰(Redux: 설치 및 세팅) (0) | 2023.10.25 |
React 쇼핑몰(Context API) (0) | 2023.10.24 |