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
相关产品推荐
相关产品推荐

