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

React中fetch使用方法及组件渲染两次、嵌套属性访问崩溃问题

问题解答

1. 为什么访问 data.goals[0].gs_id 会崩溃?怎么正确获取数据?

你遇到的崩溃问题,核心是初始状态和异步数据加载的时序不匹配:

  • 组件初始化时,你把state.data设成了空数组[],但从服务器返回的result应该是一个包含goals数组的对象(比如{ goals: [...] })。
  • 第一次render时,data还是初始的空数组,没有goals属性,所以data.goals是undefined,再去访问undefined[0]就会直接抛出错误,导致应用崩溃。

解决方法有几种,推荐用以下两种方式:

方法一:使用可选链操作符 ?.(最简洁)

它会在访问属性前自动检查是否为null/undefined,如果是就返回undefined而不崩溃,还可以搭配默认值提示加载状态:

render() {
  const { data } = this.state;
  return <h1>{data?.goals?.[0]?.gs_id || '加载中...'}</h1>;
}

方法二:条件渲染(适合复杂逻辑场景)

先判断数据是否准备就绪,再渲染对应内容:

render() {
  const { data } = this.state;
  // 先检查goals是否存在且有数据
  if (!data.goals || data.goals.length === 0) {
    return <h1>加载中...</h1>;
  }
  // 数据就绪后再渲染目标内容
  return <h1>{data.goals[0].gs_id}</h1>;
}

另外建议把初始state.data改成空对象{},因为服务器返回的是对象而非数组,语义更准确:

constructor(props) {
  super(props);
  this.state = { data: {} }; // 改为空对象
}

2. 能不能在render方法里执行fetch并写入state?

绝对不可以!原因有两点:

  • render是React用来描述UI的纯函数,它的执行应该是无副作用的。如果在render里调用fetch,每次组件渲染(比如state变化、props变化)都会触发新的网络请求,会导致无限循环的请求,既会打崩服务器,也会让应用卡死。
  • React的生命周期设计中,数据获取这类副作用操作应该放在组件挂载完成后执行。类组件里推荐用componentDidMount(你当前用的componentWillMount已经被React废弃,不建议继续使用),函数组件则用useEffect。

修正后的生命周期写法:

componentDidMount() { // 替换componentWillMount
  fetch("http://localhost:3001")
    .then(response => response.json())
    .then(result => this.setState({ data: result }))
    .catch(e => console.log(e));
}

3. 为什么render方法被调用了两次?

这是完全正常的现象:

  • 第一次调用:组件初始化,使用初始的state.data(空对象/数组)渲染初始UI。
  • 第二次调用:fetch请求完成后,你调用setState更新了state.data,React检测到state变化,会重新调用render渲染最新的UI。

只要处理好初始状态的空值判断,两次render不会影响应用功能。

内容的提问来源于stack exchange,提问作者user11700058

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:39:53