You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native购物车无法添加配菜并计算价格问题求助

解决React Native中Context Hook购物车无法添加配菜的问题

核心问题在于当前购物车状态管理逻辑仅处理主餐的添加,未关联配菜的选中状态与价格计算。以下是针对性的修改方案:


1. 重构购物车Context的状态与操作逻辑

调整购物车项结构,让每个主餐项关联选中的配菜列表,并新增配菜勾选/取消的处理方法:

import React, { createContext, useContext, useReducer } from 'react';

const CartContext = createContext();

const cartReducer = (state, action) => {
  switch (action.type) {
    case 'ADD_MEAL': {
      const existingMealIndex = state.cartItems.findIndex(item => item.id === action.payload.meal.id);
      if (existingMealIndex >= 0) {
        // 主餐已存在,增加数量
        const updatedItems = [...state.cartItems];
        updatedItems[existingMealIndex].quantity += 1;
        return {
          ...state,
          cartItems: updatedItems,
          totalAmount: state.totalAmount + action.payload.meal.price
        };
      } else {
        // 新增主餐,初始化选中配菜为空
        const newMeal = {
          ...action.payload.meal,
          basePrice: action.payload.meal.price,
          quantity: 1,
          selectedAddons: []
        };
        return {
          ...state,
          cartItems: [...state.cartItems, newMeal],
          totalAmount: state.totalAmount + action.payload.meal.price
        };
      }
    }
    case 'TOGGLE_ADDON': {
      const { mealId, addon } = action.payload;
      const mealIndex = state.cartItems.findIndex(item => item.id === mealId);
      if (mealIndex < 0) return state;

      const updatedItems = [...state.cartItems];
      const targetMeal = { ...updatedItems[mealIndex] };
      const addonIndex = targetMeal.selectedAddons.findIndex(a => a.id === addon.id);

      if (addonIndex >= 0) {
        // 取消配菜,扣除对应价格
        targetMeal.selectedAddons.splice(addonIndex, 1);
        updatedItems[mealIndex] = targetMeal;
        return {
          ...state,
          cartItems: updatedItems,
          totalAmount: state.totalAmount - addon.price
        };
      } else {
        // 选中配菜,增加对应价格
        targetMeal.selectedAddons.push(addon);
        updatedItems[mealIndex] = targetMeal;
        return {
          ...state,
          cartItems: updatedItems,
          totalAmount: state.totalAmount + addon.price
        };
      }
    }
    default:
      return state;
  }
};

export const CartProvider = ({ children }) => {
  const [state, dispatch] = useReducer(cartReducer, {
    cartItems: [],
    totalAmount: 0
  });

  const addMealToCart = (meal) => dispatch({ type: 'ADD_MEAL', payload: { meal } });
  const toggleAddonSelection = (mealId, addon) => dispatch({ type: 'TOGGLE_ADDON', payload: { mealId, addon } });

  return (
    <CartContext.Provider value={{ ...state, addMealToCart, toggleAddonSelection }}>
      {children}
    </CartContext.Provider>
  );
};

export const useCart = () => useContext(CartContext);

2. 修改OrderScreen组件,绑定配菜勾选事件

为配菜的选择框绑定Context的配菜切换方法,并处理"勾选配菜时自动添加主餐"的逻辑:

import React from 'react';
import { View, Text, Button, CheckBox, FlatList, StyleSheet } from 'react-native';
import { useCart } from '../contexts/CartContext';
import dummyData from '../data/dummyData';

const OrderScreen = () => {
  const { addMealToCart, toggleAddonSelection, cartItems, totalAmount } = useCart();

  const renderMealItem = ({ item: meal }) => (
    <View style={styles.mealCard}>
      <Text style={styles.mealName}>{meal.name}</Text>
      <Text style={styles.mealPrice}>价格: ${meal.price.toFixed(2)}</Text>
      <Button title="添加到购物车" onPress={() => addMealToCart(meal)} />

      <Text style={styles.addonTitle}>可选配菜:</Text>
      {meal.addons.map(addon => {
        const isAddonSelected = cartItems.find(cartMeal => cartMeal.id === meal.id)?.selectedAddons.some(a => a.id === addon.id) || false;
        return (
          <View key={addon.id} style={styles.addonItem}>
            <CheckBox
              value={isAddonSelected}
              onValueChange={(checked) => {
                // 若勾选配菜时主餐未在购物车,自动添加主餐
                if (checked && !cartItems.find(cartMeal => cartMeal.id === meal.id)) {
                  addMealToCart(meal);
                }
                toggleAddonSelection(meal.id, addon);
              }}
            />
            <Text>{addon.name} (+${addon.price.toFixed(2)})</Text>
          </View>
        );
      })}
    </View>
  );

  return (
    <View style={styles.container}>
      <FlatList
        data={dummyData.meals}
        keyExtractor={(item) => item.id}
        renderItem={renderMealItem}
      />
      <View style={styles.totalBar}>
        <Text style={styles.totalText}>购物车总计: ${totalAmount.toFixed(2)}</Text>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: { flex: 1, padding: 20 },
  mealCard: { marginVertical: 10, padding: 10, borderWidth: 1, borderRadius: 8 },
  mealName: { fontSize: 18, fontWeight: 'bold' },
  mealPrice: { marginVertical: 5 },
  addonTitle: { marginTop: 10, fontSize: 16, fontWeight: '500' },
  addonItem: { flexDirection: 'row', alignItems: 'center', marginVertical: 5 },
  totalBar: { marginTop: 20, paddingTop: 10, borderTopWidth: 1 },
  totalText: { fontSize: 20, fontWeight: 'bold' }
});

export default OrderScreen;

3. 确保dummyData的结构符合要求

主餐对象需包含addons数组,存储配菜信息:

const dummyData = {
  meals: [
    {
      id: 'm1',
      name: 'Chicken Fajita',
      price: 12.99,
      addons: [
        { id: 'a1', name: 'Garlic Sauce', price: 1.99 },
        { id: 'a2', name: 'Extra Cheese', price: 2.49 }
      ]
    },
    // 其他主餐数据...
  ]
};

export default dummyData;

内容的提问来源于stack exchange,提问作者Bashamlan Salem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 03:50:42