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

React+AWS Amplify+Datastore查询Promise报错求助

解决AWS Amplify DataStore查询Basket时的两个错误

错误分析

  1. 未处理的Promise拒绝 + 类型错误:o.userID不是函数
    错误出现在b.restaurantID('eq', restaurant.id).userID('eq', dbUser.id)代码行,原因是AWS Amplify DataStore的多条件查询不能直接链式调用字段方法,必须用and()方法组合多个查询条件。

  2. 类型错误: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 07:05:24