React函数组件因API未预加载触发map调用报错排查
问题解决方法
核心问题分析
- 初始状态未初始化:
useState()未设置初始值,默认是undefined,组件首次渲染时调用room.map()必然报错。 - API返回数据结构不匹配:从请求URL
/rooms/${params.hotel_id}/${params.room_id}来看,接口应该返回单个房间对象而非数组,map是数组专属方法,用在单个对象上完全不适用。
具体修复步骤
1. 初始化状态并添加存在性判断
先给room设置合理初始值,渲染时先判断数据是否存在,避免直接调用方法:
// 如果接口返回数组,初始化为空数组 let [room, setRoom] = useState([]); // 如果接口返回单个对象,初始化为null // let [room, setRoom] = useState(null);
渲染时增加条件判断:
// 数组场景:确保数组有内容再调用map {room.length > 0 && room.map((r) => ( <span key={r.id}>{r.room_name}</span> ))} // 单个对象场景:直接判断对象是否存在再访问属性 {room && <span>{room.room_name}</span>}
2. 修正API数据渲染逻辑
结合Postman测试结果,如果返回的是单个房间对象,直接访问属性即可,完全不需要map:
<div className='room-selection'> <h5>Your room selection:</h5> {room && room.room_name} </div> <div className='room-pricing'> <h5>Your price summary:</h5> {room && (room.room_rate * props.lengthStay)} </div> <section className='hotel-details'> <h6>Hotel</h6> {room && room.hotel_name} {room && room.location_name} {room && room.country} </section>
3. 优化useEffect依赖项
把params.hotel_id和params.room_id加入useEffect的依赖数组,确保URL参数变化时自动重新请求数据:
useEffect(() => { let url = `http://localhost:5000/rooms/${params.hotel_id}/${params.room_id}`; fetch(url) .then((response) => response.json()) .then((data) => { // 单个对象直接设置 setRoom(data); // 如果返回的是包含单个元素的数组,取第一个元素 // setRoom(data[0]); }) .catch((error) => { console.log(error); }); }, [params.hotel_id, params.room_id])
4. 可选:添加加载状态提示
增加加载状态,提升用户等待体验:
let [loading, setLoading] = useState(true); useEffect(() => { let url = `http://localhost:5000/rooms/${params.hotel_id}/${params.room_id}`; fetch(url) .then((response) => response.json()) .then((data) => { setRoom(data); setLoading(false); }) .catch((error) => { console.log(error); setLoading(false); }); }, [params.hotel_id, params.room_id]) // 渲染时展示加载提示 {loginStatus === true && <> {loading ? <p>加载中...</p> : ( // 原有的预订详情、房间信息等渲染内容 )} </>}
内容的提问来源于stack exchange,提问作者Simone Ghilotti
相关产品推荐
相关产品推荐

