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
相关产品推荐
相关产品推荐

