React+AWS Amplify+Datastore查询Promise报错求助
解决AWS Amplify DataStore查询Basket时的两个错误
错误分析
未处理的Promise拒绝 + 类型错误:o.userID不是函数
错误出现在b.restaurantID('eq', restaurant.id).userID('eq', dbUser.id)代码行,原因是AWS Amplify DataStore的多条件查询不能直接链式调用字段方法,必须用and()方法组合多个查询条件。类型错误:null不是对象(评估restaurant.id时)
restaurant初始状态为null,组件挂载或restaurant未完成赋值时,直接访问restaurant.id会触发空值报错;同时dbUser也可能存在未加载完成的情况,会导致后续逻辑执行失败。
修复步骤及代码调整
1. 修正DataStore多条件查询写法
将链式调用的字段条件改为用and()包裹组合:
// 错误写法 b.restaurantID('eq', restaurant.id).userID('eq', dbUser.id) // 正确写法 b.and(b => [ b.restaurantID('eq', restaurant.id), b.userID('eq', dbUser.id) ])
2. 增加空值判断,避免访问null/undefined属性
在执行DataStore查询和创建新Basket前,先校验dbUser和restaurant是否存在:
调整查询Basket的useEffect
useEffect(() => { if (!dbUser || !restaurant) return; DataStore.query(Basket, (b) => b.and(b => [ b.restaurantID('eq', restaurant.id), b.userID('eq', dbUser.id) ]) ).then((baskets) => setBasket(baskets[0])) .catch(err => console.error('查询Basket失败:', err)); }, [dbUser, restaurant]);
调整createNewBasket函数
const createNewBasket = async () => { if (!dbUser || !restaurant) return null; const newBasket = await DataStore.save( new Basket({ userID: dbUser.id, restaurantID: restaurant.id }) ); setBasket(newBasket); return newBasket; };
调整addDishToBasket函数
增加对createNewBasket返回值的校验,避免使用null的id:
const addDishToBasket = async (dish, quantity) => { if (!dbUser || !restaurant) { console.error('用户或餐厅信息未加载完成'); return; } let theBasket = basket || (await createNewBasket()); if (!theBasket) return; const newDish = await DataStore.save( new BasketDish({ quantity, Dish: dish, basketID: theBasket.id }) ); setBasketDishes([...basketDishes, newDish]); };
修正totalPrice的初始值
避免restaurant?.deliveryFee为undefined时,reduce初始值异常:
const totalPrice = basketDishes.reduce( (sum, basketDish) => sum + basketDish.quantity * basketDish.Dish.price, restaurant?.deliveryFee || 0 );
完整修复后的代码
import { createContext, useState, useEffect, useContext } from "react"; import { DataStore } from "aws-amplify"; import { Basket, BasketDish } from "../models"; import { useAuthContext } from "./AuthContext"; const BasketContext = createContext({}); const BasketContextProvider = ({ children }) => { const { dbUser } = useAuthContext(); const [restaurant, setRestaurant] = useState(null); const [basket, setBasket] = useState(null); const [basketDishes, setBasketDishes] = useState([]); const totalPrice = basketDishes.reduce( (sum, basketDish) => sum + basketDish.quantity * basketDish.Dish.price, restaurant?.deliveryFee || 0 ); useEffect(() => { if (!dbUser || !restaurant) return; DataStore.query(Basket, (b) => b.and(b => [ b.restaurantID('eq', restaurant.id), b.userID('eq', dbUser.id) ]) ).then((baskets) => setBasket(baskets[0])) .catch(err => console.error('查询Basket失败:', err)); }, [dbUser, restaurant]); useEffect(() => { if (!basket) return; DataStore.query(BasketDish, (bd) => bd.basketID("eq", basket.id)) .then(setBasketDishes) .catch(err => console.error('查询BasketDish失败:', err)); }, [basket]); const addDishToBasket = async (dish, quantity) => { if (!dbUser || !restaurant) { console.error('用户或餐厅信息未加载完成'); return; } let theBasket = basket || (await createNewBasket()); if (!theBasket) return; const newDish = await DataStore.save( new BasketDish({ quantity, Dish: dish, basketID: theBasket.id }) ); setBasketDishes([...basketDishes, newDish]); }; const createNewBasket = async () => { if (!dbUser || !restaurant) return null; const newBasket = await DataStore.save( new Basket({ userID: dbUser.id, restaurantID: restaurant.id }) ); setBasket(newBasket); return newBasket; }; return ( <BasketContext.Provider value={{ addDishToBasket, setRestaurant, restaurant, basket, basketDishes, totalPrice, }} > {children} </BasketContext.Provider> ); }; export default BasketContextProvider; export const useBasketContext = () => useContext(BasketContext);
内容的提问来源于stack exchange,提问作者jimmy mutinda
相关产品推荐
相关产品推荐

