리덕스(Redux) 심화과정 - Object, Array를 관리해보자

//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>
    )

// /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

풀이

// 우선 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

풀이

// 사용할 함수를 만들고
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으로 구분하고있다.

풀이

//기존 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