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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 20:06:04