React渲染报错:[object Promise]不可作为合法React子节点
问题根因
React只允许渲染字符串、数字、JSX元素、数组、Fragment、布尔值/null/undefined这些合法子节点,不支持直接渲染Promise对象。
你在JSX中直接调用返回Promise的getBookings()方法时,表达式的求值结果就是Promise实例本身,即使你在.then()回调中返回了JSX结构,那也只是Promise异步resolve后的内部值,渲染同步执行阶段拿到的始终是Promise对象,因此触发报错。
除此之外你的写法还有一个严重问题:接口请求直接写在JSX渲染表达式里,组件每次重渲染都会重复触发接口调用,产生大量无效请求,极易引发数据不一致、页面卡顿问题。
修复方案
核心思路是分离数据请求和渲染逻辑:接口请求放在副作用钩子中执行,请求结果存入组件状态,渲染阶段直接读取状态值生成JSX即可。
- 首先在组件内声明所需状态,存储当前行程的预订数据、加载状态
import { useState, useEffect } from 'react'; // 组件内部代码 const [rideBookings, setRideBookings] = useState([]); const [isLoading, setIsLoading] = useState(false);
- 将接口请求移入
useEffect,配置正确的依赖项避免重复请求
useEffect(() => { // 未登录状态下跳过请求 if (!currentUser.id) return; const loadBookings = async () => { setIsLoading(true); try { const bookingList = await getBookings(r.id); setRideBookings(bookingList); } catch (err) { console.error('获取预订信息失败:', err); setRideBookings([]); } finally { setIsLoading(false); } }; loadBookings(); // 依赖项为行程id、当前用户id,值变化时才会重新触发请求 }, [r.id, currentUser.id]);
- 修正JSX渲染逻辑,移除JSX中的直接Promise调用,基于已存在的状态渲染内容
{ !currentUser.id ? '' : isLoading ? <div>加载中...</div> : (() => { const filteredBookings = rideBookings.filter(b => parseInt(b.uid) === parseInt(currentUser.id)); if (rideBookings.length > 0 && filteredBookings.length > 0) { return ( <div className="d-flex justify-content-center align-items-center"> <div className='contact-d'> <a href={`tel:${r.phone}`} className="btn rounded-pill border-0 py-3 mb-2 mb-md-0 mt-2 mt-md-0 calldriver mx-2">call</a> <Link to="/chat-booked" className="btn rounded-pill border-0 py-3 mb-2 mb-md-0 calldriver mx-2">Messag</Link> <a href="mailto:support@puchkoo.com" className="btn rounded-pill py-3 reportride mx-2">Report Ride</a> </div> </div> ) } return ''; })() }
额外优化建议
你原来的getBookings函数手动嵌套了一层Promise包装属于冗余写法,fetch本身就返回Promise,可以简化为:
const getBookings = async (rid) => { const res = await fetch(`${process.env.REACT_APP_SERVER_URL}/bookings/${rid}`, { method: 'GET', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` } }); const data = await res.json(); if (data.error) throw new Error(data.message); setBookings(data.data); return data.data; }
内容的提问来源于stack exchange,提问作者Harwinder Singh
相关产品推荐
相关产品推荐

