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

React+AWS Amplify DataStore中如何获取Promise类型的菜品数据?

问题:React中使用AWS Amplify DataStore时关联字段返回Promise无法访问属性

开发React项目时,使用AWS Amplify DataStore查询OrderDish数据后,发现dishItem.Dish是Promise类型,无法直接访问name、price等属性。怀疑是Amplify版本更新导致(教程示例无此问题),尝试过.then()和async/await但未找到正确实现方式。

相关代码

import {Card, Descriptions, Divider, List, Button} from 'antd';
import { useEffect, useState } from 'react';
import {useParams} from 'react-router-dom';
import {DataStore} from '@aws-amplify/datastore';
import {Order, OrderDish, User} from '../../models';


const DetailedOrder = () => {
    const {id} = useParams();
    const [order, setOrder] = useState(null);
    const [customer, setCustomer] = useState(null);
    const [dishes, setDishes] = useState([]);

    useEffect(() => {
        DataStore.query(Order, id).then(setOrder);
    }, [id]);

    useEffect(() => {
        if(order?.userID) {
            DataStore.query(User, order.userID).then(setCustomer);
        }
    }, [order?.userID]);

    useEffect(() => {
        if(!order?.id){
            return;
        }
        DataStore.query(OrderDish, c => c.orderID.eq(order.id)).then(setDishes);
    }, [order?.id])

    console.log(dishes);

    return (
        <Card title={`Order #${id}` } style={{ margin: 20 }}>
            <Descriptions bordered column={{ lg:1, md:1, sm:1 }}>
                <Descriptions.Item label="Customer">{customer?.name}</Descriptions.Item>
                <Descriptions.Item label="Customer Address">{customer?.address}</Descriptions.Item>
            </Descriptions>
            <Divider />
            <List 
                dataSource={dishes}
                renderItem={(dishItem) => (
                <List.Item>
                    <div style={{fontWeight: 'bold'}}>{dishItem.Dish.name} x{dishItem.quantity}</div>
                    <div>${dishItem.Dish.price}</div>
                </List.Item>
            )}/>
            <Divider />
                <div style={styles.totalSumContainer}>
                    <h2 style={{fontWeight: '400'}}>Total:</h2>
                    <h2 style={styles.totalPrice}>${order?.total?.toFixed(2)}</h2>
                </div>
            <Divider />
            <div style={styles.buttonsContainer}>
                <Button block type='danger' size='large' style={styles.button}>
                    Decline Order
                </Button>
                <Button block type='primary' size='large' style={styles.button}>
                    Accept Order
                </Button>
            </div>
            <Button block type='primary' size='large'>
                Ready For Pickup
            </Button>
        </Card>
    );
};

const styles = {
    totalSumContainer: {
      flexDirection: 'row',
      display: 'flex',
    },
    totalPrice: {
      marginLeft: 'auto',
      fontWeight: 'bold',
    },
    buttonsContainer: {
      display: 'flex',
      paddingBottom: 30,
    },
    button: {
      marginRight: 10,
      marginLeft: 10,
      color: 'white',
    },
  };

export default DetailedOrder; 

控制台现象

查询返回的dishes数组中,每个dishItem的Dish字段为Promise对象,无法直接读取属性。


解决方法

方式1:预解析关联数据并存入状态

在查询OrderDish后,逐个解析关联的Dish对象,将完整数据存入状态:

  1. 修改useEffect中的查询逻辑:
useEffect(() => {
    if(!order?.id){
        return;
    }
    const fetchDishes = async () => {
        const orderDishes = await DataStore.query(OrderDish, c => c.orderID.eq(order.id));
        // 批量解析关联的Dish数据
        const dishesWithData = await Promise.all(
            orderDishes.map(async od => ({
                orderDish: od,
                dish: await od.Dish
            }))
        );
        setDishes(dishesWithData);
    };
    fetchDishes();
}, [order?.id])
  1. 更新List的渲染逻辑:
<List 
    dataSource={dishes}
    renderItem={(item) => (
    <List.Item>
        <div style={{fontWeight: 'bold'}}>{item.dish.name} x{item.orderDish.quantity}</div>
        <div>${item.dish.price}</div>
    </List.Item>
)}/>

方式2:使用DataStore的populate参数(新版本支持)

如果你的Amplify版本支持,可直接在查询时指定加载关联字段:

useEffect(() => {
    if(!order?.id){
        return;
    }
    const fetchDishes = async () => {
        const orderDishes = await DataStore.query(OrderDish, 
            c => c.orderID.eq(order.id),
            { populate: ['Dish'] } // 直接加载关联的Dish数据
        );
        setDishes(orderDishes);
    };
    fetchDishes();
}, [order?.id])

此方式下dishItem.Dish会直接解析为Dish对象,原渲染代码无需修改。

方式3:React 18+ 结合Suspense处理异步组件

  1. 创建异步子组件渲染单个菜品:
const DishItem = async ({ dishItem }) => {
    const dish = await dishItem.Dish;
    return (
        <List.Item>
            <div style={{fontWeight: 'bold'}}>{dish.name} x{dishItem.quantity}</div>
            <div>${dish.price}</div>
        </List.Item>
    );
};
  1. 父组件用Suspense包裹List:
<Suspense fallback={<div>Loading dishes...</div>}>
    <List 
        dataSource={dishes}
        renderItem={(dishItem) => <DishItem dishItem={dishItem} />}
    />
</Suspense>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 15:30:49