【问题标题】:cant add existing product in cart in reducer in redux with react native无法在redux的reducer中添加购物车中的现有产品与react native
【发布时间】:2021-05-26 23:48:18
【问题描述】:

我正在开发一个具有母店的 react native 应用程序,正在使用 redux 处理全局状态,并且在我的减速器中,我必须处理添加到购物车,如果购物车中不存在产品或产品存在于购物车中,我的目标只是在不增加总产品数量的情况下增加其数量 这是我的动作和减速器

export const ADD_TO_CART = 'ADD_TO_CART';
export const ADD_QUANTITY = 'ADD_QUANTITY';
export const SUB_QUANTITY = 'SUB_QUANTITY';

export const DELETE_ITEM = 'DELETE_ITEM';


export const addToCart = (payload) => {
    type: ADD_TO_CART,
    payload
}

export const addQuantity = (payload) => {
    type: ADD_QUANTITY,
    payload
}

export const subQuantity = (payload) => {
    type: SUB_QUANTITY,
    payload
}

export const deleteItem = (payload) => {
    type: DELETE_ITEM,
    payload
}

我的购物车减速器

import { ADD_TO_CART,DELETE_ITEM,SUB_QUANTITY,ADD_QUANTITY} from '../actions/cartItems';

const initialState = {
    itemsCount : 0,
    cartItems:[],
    cartTotalAmount:0,

}

const cartReducer = (state=initialState, action)=>{
    switch(action.type){
        case ADD_TO_CART:
            let cart = {
                id:action.payload.itemId,
                quantity:action.payload.quantity,
                name:action.payload.itemTitle,
                image:action.payload.itemImg,
                price:action.payload.itemPrice,
                cartAmount:action.payload.quantity * action.payload.itemPrice
            }
            
            if(state.itemsCount === 0){
                state.cartItems.push(cart);//just push the cart
                return {
                    ...state,
                    itemsCount:state.itemsCount+1,
                    cartTotalAmount:state.cartItems.map(item => {
                        state.cartTotalAmount+item.cartAmount
                    })
                }
            }else{
                let exists =false;
                let i =0;
                while(i<state.cartItems.length){
                    if(state.cartItems[i].id === action.payload.itemId){
                        state.cartItems[i].quantity++;
                        exists = true;
                    }
                    return{
                        ...state,
                        itemsCount:state.itemsCount
                    }
                    i++;
                }

                state.cartItems.map((key,item) => {
                    if(item.id === action.payload.itemId){
                        // {...item,quantity:item.quantity+1}
                        state.cartItems[key].quantity++;
                        exists = true
                    }
                    return {
                        ...state,
                        itemsCount:state.itemsCount,
                    }
                })
                if(!exists){
                    let _cart = {
                        id:action.payload.itemId,
                        quantity:action.payload.quantity,
                        name:action.payload.itemTitle,
                        image:action.payload.itemImg,
                        price:action.payload.itemPrice,
                        cartAmount:action.payload.quantity * action.payload.itemPrice
                    }
                    state.cartItems.push(_cart)
                    return {
                        ...state,
                        itemsCount:state.itemsCount+1,
                        cartTotalAmount:state.cartItems.map(item => {
                            state.cartTotalAmount+item.cartAmount
                        })
                    }
                }


            }
        case ADD_QUANTITY:
            return {
                ...state,
                cartItems:state.cartItems.map(
                    item => item.id === action.payload.itemId
                    ? {...item, quantity: item.quantity+1 }
                    : item 
                ),
            }
        case DELETE_ITEM:
            let newCartItems = state.cartItems.filter(
                (item) => {return item.id != action.payload.itemId}
            )
            let count = state.itemsCount-1;
            return {
                ...state,
                itemsCount:count,
                cartItems:newCartItems,
            }
        case SUB_QUANTITY:
            return {
                ...state,
                cartItems:state.cartItems.map(
                    item => item.id === action.payload.itemId 
                    ? {...item, quantity: item.quantity-1 } 
                    : item  
                ),
            }
        
        // case ADD_TO_WISH_LIST:
        //     for(let i=0; i < state.wishListItems.length; i++){
        //         if(state.wishListItems[i].id === action.item.id){
        //             return {
        //                 ...state,
        //                 wishListItems: state.wishListItems.map(item => item.id === action.item.id ?
        //                     { ...item, quantity: item.quantity+1 } :item
        //                 ) ,
        //             }
        //         }
        //         else{
        //             let updatedWishListItems = [...state.wishListItems, action.item];   
        //             let count = state.wishCount + 1;
        //         }
        //     }
        //     return{
        //         ...state,
        //         wishCount : count,
        //         wishListItems :updatedWishListItems
        //     }
        
        // case DELETE_FROM_WISH_LIST:
        //     let newWishListItems = state.wishListItems.filter(
        //         (item)=>{
        //          return item.id!=action.item.id
        //         }
        //      );
            
        //      return {
        //         ...state,
        //         wishListItems : newWishListItems , 
        //     }  
        default:
            return state
    }
        
}  

export default cartReducer;

itemsCount === 0 works 时,reducer 中添加到购物车的第一种情况,但是当购物车有多个项目时,reducer 无法正确执行并且需要帮助

【问题讨论】:

    标签: reactjs react-native redux action reducers


    【解决方案1】:

    问题

    1. 不要将itemsCountcartTotalAmount 值存储在状态中,这些值很容易从状态数据中导出。存储重复或派生数据是反模式。

      const initialState = {
        itemsCount : 0, // <-- easily computed from cart items
        cartItems:[],
        cartTotalAmount:0, // <-- easily computed from cart items
      }
      
    2. 不要通过直接推入您的 cartItems 数组来改变您的状态。

      state.cartItems.push(cart); // <-- mutates state reference
      
    3. 您需要先搜索cartItems,看看您是否已经添加了购物车商品。

    解决方案

    case ADD_TO_CART:
      const {
        itemId,
        itemImg,
        itemPrice,
        itemTitle,
        quantity,
      } = action.payload;
    
      // search if item is already in cart by item id
      const inCart = state.cartItems.some(item => item.id === itemId);
    
      if (inCart) {
        // already in cart, shallow copy cart items
        return {
          ...state,
          cartItems: state.cartItems.map(item => item.id === itemId ? {
            // found item, shallow copy item and update quantity property
            ...item,
            quantity: item.quantity + 1,
          } : item),
        }
      } else {
        return {
          ...state,
          cartItems: [
            // shallow copy cart items
            ...state.cartItems,
            // add new cart item
            {
              id: itemId,
              quantity: quantity,
              name: itemTitle,
              image: itemImg,
              price: itemPrice,
            }
          ],
        }
      }
    
      ...
    

    您可以对更新购物车项目的其他操作类型应用类似的更新模式。

    在你的 UI 中计算 itemsCount

    const itemsCount = cartItems.reduce((count, { quantity }) => count + quantity, 0)
    

    计算cartTotalAmount

    const cartTotalAmount = cartItems.reduce(
      (totalAmount, { price, quantity }) => totalAmount + quantity * price,
      0,
    );
    

    这些可以在一次传递中组合成一个计算

    const { cartTotalAmount, itemsCount } = cartItems.reduce(
      ({ cartTotalAmount, itemsCount }, { price, quantity }) => ({
        cartTotalAmount: cartTotalAmount + quantity * price,
        itemsCount: itemsCount + quantity,
      }),
      {
        cartTotalAmount: 0,
        itemsCount: 0,
      },
    );
    

    【讨论】:

    • 谢谢让我试一试,不过我应该将 cartTotalAmount 和 itemsCount 放在同一个减速器中,因为最终我必须在我的应用程序的全局状态中使用它们
    • @joshington 不,它们是派生的“状态”,您应该创建一个状态选择器函数来读取此状态并计算值。与useSelectormapStateToProps 一起使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-02
    • 1970-01-01
    相关资源
    最近更新 更多