Written by
Parkdev
on
on
[React] Redux3 - Object와 Array를 관리해보자
리덕스(Redux) 심화과정 - Object, Array를 관리해보자
- Object의 값을 관리하려면 다음과 같이 작성하면 된다.
//store.js
let user = createSlice({
name: 'user',
initialState : { name : 'kim', age : 20 },
// 값 변경하기 위해 추가해야하는 reducers
reducers : {
changeName(state) {
//return을 사용하지 않고 직접 수정해도 무방
state.name = 'park'
},
changeName2(state) {
return 'john ' + state.name
},
increaseAge(state, action) { // 이런식으로 파라미터를 받는함수로도 만들 수 있다.
state.age += action.payload; // 받은 값을 사용하려면 payload를 사용해야한다.ㄴ
}
}
})
export let { changeName, increaseAge } = user.actions
// Cart.js
import { changeName, increaseAge } from '../store.js'
function Cart() {
let state = useSelector((state) => state)
let dispatch = useDispatch()
return (
..본문..
{state.user.age}
<button className='btn btn-primary' onClick={()=>{dispatch(increaseAge(10))} }> age + 1 </button>
)
- 이처럼 Object자료형 수정이 매우 편하므로, 문자 하나만 사용하는 경우에도 object형으로 작성하는 경우도 존재한다.
- 인수를 받아서 사용할 수도 있다. (action, 및 payload의 사용)
- 만약 slice파일이 너무 길어지면 별도의 파일에 분리하여 작성할 수 있다.
// /store/userSlice.js
import { createSlice } from "@reduxjs/toolkit";
// 값 변경함수를 넣어보자
let user = createSlice({
name: 'user',
initialState : { name : 'kim', age : 20 },
// 값 변경하기 위해 추가해야하는 reducers
reducers : {
changeName(state) {
//직접 수정해도 무방
state.name = 'park'
},
changeName2(state) {
return 'john ' + state.name
},
increaseAge(state, action) {
state.age += action.payload;
}
}
})
export default user;
export let { changeName, increaseAge } = user.actions
// 이렇게 바꾸었을때 함수를 불러올때 변경한 위치로부터 불러와야한다.
import { changeName, increaseAge } from '../store/userSlice.js'
예제1
- table안에 +버튼을 눌렀을때 해당행의 수량을 +1 하는 기능을 만들어보자
풀이
// 우선 increaseCount함수를 작성
let items = createSlice({
name: 'items',
initialState: [
{id : 0, name : 'White and Black', count : 2},
{id : 2, name : 'Grey Yordan', count : 1}
],
reducers: {
// 예제: Cart의 수량 그리고 수량 변경 함수를 넣어보자
increaseCount(state, action) {
// index로 처리하지말고 id매칭으로 처리
state.find((x) => x.id == action.payload).count += 1;
}
}
})
// 다른페이지에서 사용할 수 있도록 export
export let { increaseCount } = items.actions;
// cart.js
// increastCount 사용설정
import { increaseCount } from '../store.js'
// 본문에 함수사용 삽입
<tbody>
{
itemsState.map((item) => {
return (
<tr>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{item.count}</td>
<td>
<button onClick={()=>dispatch(increaseCount(item.id)) }>+</button>
</td>
</tr>
)
})
}
</tbody>
예제2
- Detail page의 주문하기 버튼을 클릭하면 장바구니 항목에 추가해보자
풀이
// 사용할 함수를 만들고
reducers: {
addItem (state, action) {
// object양식이 동일하지 않기때문에 수정해서 집어넣어주었다.
let item = { id: action.payload.id, name: action.payload.title, count: 1}
state.push(item)
}
// 밖에서 사용할 수 있도록 export하고
export let { increaseCount, addItem } = items.actions;
// Detail.js
// addItem함수 사용 설정
import { addItem } from "../store.js";
function Detail() {
...
// 사용할 state, 그리고 함수를 사용할 수 있는 설정을 진행한 후
//let itemsState = useSelector((state) => state.items)-> 필요없다 (TIL 1)
let dispatch = useDispatch()
...
return (
//..이전내용..
<button className="btn btn-danger" onClick={()=>{
dispatch(addItem(찾은상품)); //함수를 실행시켜주고
window.alert('장바구니 추가'); //알럿과 함께
navigate('/cart')}} //확인해주기위해 바로 페이지 이동을 해주게 만들었다.
>주문하기</button>
//..이후내용..
)
}
심화 예제 3
- 장바구니 항목 삭제 기능 추가하기
풀이
//해당 Slice>reducer에 함수 추가하기
deleteItem (state, action) {
let index = state.findIndex((a) => a.name == action.payload);
state.splice(index,1);
}
//export
export let { deleteItem } = items.actions;
//Cart.js
// 사용설정
import { deleteItem } from '../store.js'
let dispatch = useDispatch()
// 기능 연결
<button className='btn btn-warning' onClick={()=>dispatch(deleteItem(item.name)) }>아이템삭제</button>
//현재 케이스에서는 id가 중복되는 버그가 있기때문에 다른 고유값을 가진 name으로 구분하고있다.
- 중복상품 추가시 기존 아이템 count +1기능
풀이
//기존 addItem함수의 변경을 진행
addItem (state, action) {
let found = state.find((a)=>a.name == action.payload.title);
if (found) {
found.count++
} else {
let item = { id: action.payload.id, name: action.payload.title, count: 1};
state.push(item);
}
// 해당 문에 역시 현재 id가 중복되는 버그가 존재하여 name으로 구분하고있다.
오늘의 TIL
-
TIL1: 함수만 사용하는것이라면 useDispatch()만 가져오면된다. (useSelector을 사용할 필요가 없다)
-
지금의 Redux의 사용방식은 Redux Toolkit의 사용방법이다. (Redux의 사용성 개선 버전)