React组件调用async异步函数获取数据返回undefined如何解决
核心问题原因
- 所有
async函数的返回值本质是Promise对象,你没有通过await或者.then()处理的前提下,直接调用getStudents()拿到的不是请求返回的学生数组,而是处于pending状态的Promise实例,读取它的length属性自然拿不到预期结果。 - React函数组件是同步执行渲染的,无法阻塞渲染等待异步请求返回结果,必须用状态存储异步返回的数据,等请求完成更新状态触发重新渲染,才能渲染正确的数值。
最简解决方案
使用React内置的useState和useEffect钩子实现,修改后的代码如下:
import { useState, useEffect } from 'react'; async function getStudents() { var reqObj = new RequestHandler("/students/all/"); let { students } = await reqObj.sendRequest(); console.log(students, students.length); return students; } export default function Students(props) { // 初始化学生列表状态,默认值设为空数组避免首次渲染读length报错 const [students, setStudents] = useState([]); // 组件首次挂载后触发异步请求 useEffect(() => { // useEffect回调不能直接声明为async,内部封装异步执行函数即可 const fetchStudents = async () => { const result = await getStudents(); setStudents(result); }; fetchStudents(); }, []); // 空依赖数组表示该逻辑仅在组件首次渲染完成后执行一次 return ( <main className="content-section"> <h1>Students</h1> <span className="help-text"> You have {`${students.length}`} students. </span> </main> ); }
新手必知基础补充
- 只要是
async声明的函数,不管内部return的是什么值,外层拿到的永远是Promise包装对象,想要拿到内部的实际返回值,必须用await(只能在另一个async函数内使用)或者.then(结果 => {处理逻辑})的方式接收。 - 上述代码第一次渲染的时候,请求还没返回,用的是默认的空数组渲染,等请求完成后调用
setStudents会触发组件第二次渲染,这时候就会用拿到的真实学生数组渲染数值。 - 如果需要添加加载状态,可以额外声明一个
const [isLoading, setIsLoading] = useState(true)的状态,请求前设为true,请求完成后设为false,渲染的时候根据这个状态切换展示加载提示或者实际内容。
内容的提问来源于stack exchange,提问作者W1ck3d
相关产品推荐
相关产品推荐

