React中useState设置数组仅最后一个对象重渲染的原因与解决方法
问题描述
- 使用AWS Amplify DataStore时,尝试用Async/await获取Promise结果失败,代码执行后
dishResponse仍为Promise:
if(orderResponse?.id) { const dishResponse = await DataStore.query(OrderDish, (c) => c.orderID?.eq(orderResponse.id)); console.log('dish', dishResponse); setDishes(dishResponse); }
- 后续通过
useState定义dishes和orderDish,在useEffect中遍历dishes更新orderDish时,状态仅保留最后一个对象:
const [dishes, setDishes] = useState(); const [orderDish, setOrderDish] = useState([]); useEffect (() => { dishes?.map((orderdishItem) => ( setOrderDish(orderdishItem) ) ) },)
问题原因
- Async/await失效问题:
await只能在async函数内使用,如果这段代码所在的函数没有标记为async,await不会生效,DataStore.query返回的Promise会直接赋值给dishResponse。 - orderDish仅保留最后一个对象:
map遍历dishes时,每次调用setOrderDish(orderdishItem)都会把状态替换成单个对象,最后一次赋值会覆盖之前所有结果,因此只保留最后一个对象。
解决代码示例
1. 修复Async/await使用问题
确保包含await的代码在async函数中,React组件内可结合useEffect实现:
const [dishes, setDishes] = useState([]); useEffect(() => { const fetchDishes = async () => { if (orderResponse?.id) { const dishResponse = await DataStore.query(OrderDish, (c) => c.orderID?.eq(orderResponse.id)); console.log('dish', dishResponse); setDishes(dishResponse); } }; fetchDishes(); }, [orderResponse?.id]); // 添加依赖项,当orderResponse.id变化时重新执行查询
2. 修复orderDish状态更新问题
如果需要将dishes的所有元素存入orderDish,直接将整个数组赋值即可,无需遍历单个替换:
const [orderDish, setOrderDish] = useState([]); useEffect(() => { if (dishes) { // 直接将dishes数组赋值给orderDish setOrderDish([...dishes]); // 若需提取每个item的orderDishDishid,可生成新数组后赋值 // const processedDishes = dishes.map(item => item.orderDishDishid); // setOrderDish(processedDishes); } }, [dishes]); // 依赖项添加dishes,当dishes变化时更新状态
完整示例(结合获取Dish详情)
如果需要通过orderDishDishid批量查询对应的Dish数据,可在获取dishes后统一处理:
const [dishes, setDishes] = useState([]); const [orderDishDetails, setOrderDishDetails] = useState([]); useEffect(() => { const fetchDishesAndDetails = async () => { if (!orderResponse?.id) return; // 第一步:查询关联的OrderDish列表 const dishResponse = await DataStore.query(OrderDish, (c) => c.orderID?.eq(orderResponse.id)); setDishes(dishResponse); // 第二步:批量查询每个OrderDish对应的Dish详情 if (dishResponse.length > 0) { const detailPromises = dishResponse.map(item => DataStore.query(Dish, item.orderDishDishid) ); const dishDetails = await Promise.all(detailPromises); setOrderDishDetails(dishDetails); } }; fetchDishesAndDetails(); }, [orderResponse?.id]);
内容的提问来源于stack exchange,提问作者Dinu Gunawardana
相关产品推荐
相关产品推荐

