React Hooks 存入MongoDB数据到state后如何正确渲染避免undefined报错
问题根因
- contact初始值类型错误:
useState初始赋值为[]数组,但实际接口返回的是单个联系人对象,初始状态下数组不存在experience属性,直接调用contact.experience.map必然触发undefined报错 - loading状态逻辑颠倒:当前代码是请求成功才将loading设为true,正确逻辑应该是发起请求前开启loading,请求完成(无论成功/失败)后关闭loading
- 缺少防御性判断:访问嵌套属性、调用数组方法前没有做存在性校验,也没有基于加载状态做条件渲染限制
最优修改方案
1. 修正state初始值和getData的状态流转逻辑
// 修正contact初始值为null,匹配接口返回的对象类型 const [contact, setContact] = useState(null); const [loading, setLoading] = useState(false); const [id, setId] = useState(''); const getData = async (e) => { e.preventDefault(); // 发起请求前开启加载状态 setLoading(true); try { const response = await fetch(API_URL + id); const data = await response.json(); setContact(data); } catch (err) { console.error('数据请求失败', err); setContact(null); } finally { // 请求完成无论结果如何都关闭加载状态 setLoading(false); } console.log("DATA SAVED"); };
2. 给displayExperience增加防御性判断
用可选链和空值合并做兼容,避免属性不存在时报错:
const displayExperience = (contact) => { // 判断contact和experience是否存在,不存在默认返回空数组,不会触发map调用错误 return (contact?.experience ?? []).map((exp, index) => ( <div key={index}> <h3>{exp.company}</h3> </div> )); };
3. 渲染层增加条件判断,控制渲染时机
return ( <div className="App"> <Form onSubmit={getData}> <div className="App"> <Form.Group> <Form.Label>ID</Form.Label> <Form.Control type="text" placeholder="Add ID" onChange={(e) => setId(e.target.value)}/> </Form.Group> <Button className="mt-2" variant='dark' type="submit" >Submit</Button> </div> </Form> <div> {/* 加载中展示提示,加载完成且有有效数据才渲染工作经历 */} {loading ? <p>数据加载中...</p> : contact && displayExperience(contact)} </div> </div> )
以上方案从状态类型匹配、加载流程控制、属性访问兼容三个维度彻底避免undefined报错,不需要额外引入useEffect监听loading,直接在渲染层做条件判断即可满足需求。
内容的提问来源于stack exchange,提问作者Brian
相关产品推荐
相关产品推荐

