Redux - Cmarket Redux ๊ณผ์ œ ๐Ÿ“–

forhreverยท2023๋…„ 2์›” 27์ผ
0

๐Ÿ’ก 1. Action

์–ด๋–ค ์•ก์…˜์„ ์ทจํ•  ๊ฒƒ์ธ์ง€ ์ •์˜ํ•ด ๋†“์€ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.

payload

์ „์†ก๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•  ๋•Œ, ๋‹ค์–‘ํ•œ ์š”์†Œ๋“ค์„ ํ•จ๊ผ ๋ณด๋‚ด์–ด, ๋ฐ์ดํ„ฐ ์ „์†ก์˜ ํšจ์œจ๊ณผ ์•ˆ์ •์„ฑ์„ ๋†’ํžˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋•Œ, ๋ณด๋‚ด๊ณ ์ž ํ•˜๋Š” ๋ฐ์ดํ„ฐ ์ž์ฒด๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

Test case
Shopping Cart Actions

  • addToCart๋Š” ADD_TO_CART ์•ก์…˜์„ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • removeFromCart๋Š” REMOVE_FROM_CART ์•ก์…˜์„ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • setQuantity๋Š” SET_QUANTITY ์•ก์…˜์„ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ž‘์„ฑ ์‹œ ์œ ์˜์‚ฌํ•ญ

  • type์€ ํ•„์ˆ˜๋กœ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • type์€ ๋Œ€๋ฌธ์ž์™€ Snake Case๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • payload๋Š” action์˜ type์— ๋”ฐ๋ผ์„œ state ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผํ•œ๋‹ค.
  • ์‡ผํ•‘์นดํŠธ์— ์ถ”๊ฐ€, ์‚ญ์ œ, ๋ณ€๊ฒฝํ•  ๊ฐ’์„ ์ •ํ•  ๋•Œ, ํ•„์š”ํ•œ ๊ฐ’์„ payload์— ๋„ฃ์–ด์ค๋‹ˆ๋‹ค.

actions/index.js

export const addToCart = (itemId) => {
  return {
    type: ADD_TO_CART,
    payload: {
      quantity: 1,
      itemId
    }
  }
}
export const removeFromCart = (itemId) => {
  return {
    //TODO
    // ์œ ์–ดํด๋ž˜์Šค action ์˜ˆ์‹œ ์ฐธ๊ณ  
    type : REMOVE_FROM_CART,
    payload : {
      itemId
    }
  }
}
export const setQuantity = (itemId, quantity) => {
  return {
    //TODO
    type : SET_QUANTITY,
    payload : {
      quantity,
      itemId
    }
  }
}

๐Ÿ’ก 2. Reducer

Dispatch์—๊ฒŒ์„œ ์ „๋‹ฌ๋ฐ›์€ Action ๊ฐ์ฒด์˜ type ๊ฐ’์— ๋”ฐ๋ผ์„œ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

Test Case
Item Reducer

  • ADD_TO_CART ์•ก์…˜์— ๋”ฐ๋ผ cartItems ์ƒํƒœ๊ฐ€ ๋ณ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • REMOVE_FROM_CART ์•ก์…˜์— ๋”ฐ๋ผ cartItems ์ƒํƒœ๊ฐ€ ๋ณ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • SET_QUANTITY ์•ก์…˜์— ๋”ฐ๋ผ cartItems ์ƒํƒœ๊ฐ€ ๋ณ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฆฌ๋“€์„œ๋Š” ๋‹ค๋ฅธ ์ƒํƒœ์˜ ๊ฐ’์„ ๋ณด์กดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ž‘์„ฑ ์‹œ ์œ ์˜์‚ฌํ•ญ

  • ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•  ๋•Œ ๊ธฐ์กด์˜ ๊ฐ์ฒด๋Š” ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • Action ๊ฐ์ฒด์˜ type ๊ฐ’์— ๋”ฐ๋ผ ๋ถ„๊ธฐํ•˜๋Š” switch ์กฐ๊ฑด๋ฌธ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

itemReducer.js

const itemReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_TO_CART:
      //TODO
      return Object.assign({}, state, {
        cartItems: [...state.cartItems, action.payload]
      })
      break;
    case REMOVE_FROM_CART:
      //TODO
      let currentItem = state.cartItems.filter( el => el.itemId !== action.payload.itemId)
      return Object.assign({}, state, {
        cartItems: currentItem
      })
      break;
    case SET_QUANTITY:
      let idx = state.cartItems.findIndex(el => el.itemId === action.payload.itemId)
      //TODO
      return {
        ...state,
        cartItems: [...state.cartItems.slice(0, idx), action.payload, ...state.cartItems.slice(idx + 1)]
      }
      break;
    default:
      return state;
  }
}

๐Ÿ’ก 3. Dispatch

Reducer๋กœ Action์„ ์ „๋‹ฌํ•ด์ฃผ๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. Dispatch์˜ ์ „๋‹ฌ์ธ์ž๋กœ Action ๊ฐ์ฒด๊ฐ€ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

Test Case
Shopping Pages

  • ShoppingCart์— cartItems๊ฐ€ ๋ Œ๋”๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.
  • ADD_TO_CART ์•ก์…˜์— ๋”ฐ๋ผ ShoppingCart๊ฐ€ ๋ Œ๋”๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • REMOVE_FROM_CART ์•ก์…˜์— ๋”ฐ๋ผ ShoppingCart๊ฐ€ ๋ Œ๋”๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • SET_QUANTITY ์•ก์…˜์— ๋”ฐ๋ผ OrderSummary๊ฐ€ ๋ Œ๋”๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • Checkbox์˜ ์ƒํƒœ์— ๋”ฐ๋ผ OrderSummary๊ฐ€ ๋ Œ๋”๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ž‘์„ฑ ์‹œ ์œ ์˜์‚ฌํ•ญ

  • ์•ก์…˜ ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์š”์ฒญ์„ useDispatch()๋กœ ๋ณด๋‚ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • handleClick ํ•จ์ˆ˜ ์•ˆ์— dispatch๋กœ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œ์ผœ ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ItemListContainer.js

const dispatch = useDispatch();
const handleClick = (item) => {
    if (!cartItems.map((el) => el.itemId).includes(item.id)) {
      //TODO: dispatch ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์•„์ดํ…œ ์ถ”๊ฐ€์— ๋Œ€ํ•œ ์•ก์…˜์„ ์ „๋‹ฌํ•˜์„ธ์š”.
      dispatch(addToCart(item.id))   // ์นดํŠธ(์žฅ๋ฐ”๊ตฌ๋‹ˆ)์•ˆ์— ์•„์ดํ…œ ์ถ”๊ฐ€ ์š”์ฒญ
      dispatch(notify(`์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ${item.name}์ด(๊ฐ€) ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.`)) // ๋ฉ”์„ธ์ง€ ์š”์ฒญ
    }
    else {
      dispatch(notify('์ด๋ฏธ ์ถ”๊ฐ€๋œ ์ƒํ’ˆ์ž…๋‹ˆ๋‹ค.'))
    }
  }

ShoppingCart.js

const dispatch = useDispatch();
const handleQuantityChange = (quantity, itemId) => {
    //TODO: dispatch ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์•ก์…˜์„ ์ „๋‹ฌํ•˜์„ธ์š”.
    dispatch(setQuantity(itemId, quantity)) 
  }
  const handleDelete = (itemId) => {
    setCheckedItems(checkedItems.filter((el) => el !== itemId))
    //TODO: dispatch ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์•ก์…˜์„ ์ „๋‹ฌํ•˜์„ธ์š”.
    dispatch(removeFromCart(itemId)) // ์นดํŠธ(์žฅ๋ฐ”๊ตฌ๋‹ˆ)์•ˆ์—์„œ ์‚ญ์ œ๋  ์•„์ดํ…œ ์š”์ฒญ
  }

์˜ค๋Š˜ ํ•™์Šต์„ ๋งˆ์น˜๊ณ  ๋‚˜์„œ, ๐Ÿ“–

Action ๋ถ€๋ถ„๊ณผ Dispatch ๋ถ€๋ถ„์€ ์–ด๋Š์ •๋„ ์ดํ•ด๊ฐ€ ๋˜๊ณ  ์ฝ”๋“œ ์ž‘์„ฑํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ์ง€๋งŒ, Reducer ๋ถ€๋ถ„์„ ์ž‘์„ฑํ•  ๋•Œ, ๋ฐฐ์šด ๊ฐœ๋…๊ณผ ์กฐ๊ธˆ ๋‹ฌ๋ผ ์ž‘์„ฑํ•˜๋Š”๋ฐ ์‹œ๊ฐ„์ด ๋‹ค์†Œ ๊ฑธ๋ ธ๋‹ค. Object.assign์„ ์™œ ์“ฐ๋Š”์ง€, ํ•„์š”ํ•œ ์ด์œ ๋Š” ๋ฌด์—‡์ธ์ง€์— ๋Œ€ํ•ด ๊ถ๊ธˆํ–ˆ๋‹ค. ๋Œ€๋žต์ ์ธ ์ด์œ ๋Š” ์ฐพ์•˜์ง€๋งŒ ์ •ํ™•ํ•˜๊ฒŒ ์ด์œ ๋Š” ์•Œ์ง€ ๋ชป ํ•˜์˜€๋‹ค. ์ด ๋ถ€๋ถ„์€ ์ข€ ๋” ํ•™์Šต ํ•ด์•ผ๊ฒ ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Redux ๋ถ€๋ถ„์€ ๋ฏธ๋‹ˆ ํ”„๋กœ์ ํŠธ์—์„œ๋„ ์“ฐ์ด๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋– ํ•œ ํ˜•์‹์„ ๋„๊ณ  ์žˆ๋Š” ๊ฑด์ง€๋Š” ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค. ๊ทธ๋Ÿฌ๋ฉด์„œ Redux์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ์ž˜ ์ดํ•ดํ•˜๋ฉด ๋˜์ง€ ์•Š์„๊นŒ ์‹ถ๋‹ค. ๋ฏธ๋‹ˆ ํ”„๋กœ์ ํŠธ๋„ ์—ด์‹ฌํžˆ ๋งŒ๋“ค์–ด๋ณด์ž.

profile
๊ฐœ๋ฐœ์ž ์„ฑ์žฅ ๊ณ„๋‹จ ์˜ฌ๋ผ๊ฐ€๊ธฐ

0๊ฐœ์˜ ๋Œ“๊ธ€