如何在React渲染前使用axios完成全部数据加载避免undefined报错
React 组件的首次渲染是同步执行的,useEffect 中的异步请求会在组件首次渲染结束后才触发,所以你代码第一次执行的时候,data 还是你设置的初始值空数组,访问数组的 userId 属性自然会得到 undefined,请求成功后触发状态更新才会第二次渲染,拿到正确的 data 值。
方案1:请求完成前阻止渲染(完全满足「未拿到数据不执行后续代码」的需求)
你可以通过判断数据是否加载完成,在请求返回前直接返回空内容或者加载占位符,这样后续的打印、渲染逻辑都不会执行,修改后代码如下:
import "./styles.css"; import axios from "axios"; import { useEffect, useState } from "react"; export default function App() { // 初始值设为null更方便判断加载状态,同时和接口返回的对象类型匹配 const [data, loadData] = useState(null); useEffect(() => { const fetchData = async () => { const res = await axios.get("https://jsonplaceholder.typicode.com/todos/1"); loadData(res.data); } fetchData(); }, []); // 数据未加载完成时直接返回,后续所有代码都不会执行 if (!data) return null; // 执行到此处时data已经有有效值,不会出现undefined console.log("data", data); console.log("userId", data.userId); return ( <div className="App"> <h1>Hello CodeSandbox</h1> <h2>Start editing to see some magic happen!</h2> </div> ); }
修改后控制台只会打印一次有有效值的结果,不会再出现空值打印的情况。
方案2:可选链+默认值兜底(无需阻止渲染的场景)
如果你的页面不需要完全等待数据返回才渲染,只是要避免访问undefined属性导致的报错,可以用可选链操作符 ?. 和空值合并运算符 ?? 做兜底处理:
// 访问属性前加?.,即使data为空也不会抛出错误,只会返回undefined console.log("userId", data?.userId); // 搭配??可以设置兜底默认值 const userId = data?.userId ?? 0;
额外优化建议
- 你当前的初始state设为
[]空数组,但接口返回的是对象类型,类型不匹配,建议初始值设为null或者和返回值结构一致的默认对象,更便于判断加载状态。 - 不需要混用async/await和then链式调用,统一用async/await语法逻辑更清晰。
内容的提问来源于stack exchange,提问作者Lê Quốc Khánh
相关产品推荐
相关产品推荐

