React组件调用API先返回undefined再获数据,求解决方案
解决React useEffect异步获取API数据先返回undefined的问题
问题原因
React组件初始化时,tableData的初始state未设置默认值,默认是undefined。而getData是异步函数,API请求需要时间,所以组件第一次渲染时tableData还是undefined,等请求完成调用setTableData后才会触发重渲染拿到有效数据。这是React异步更新和API请求的正常特性,没法跳过初始渲染直接拿到数据,但可以通过以下方式优化。
解决方案
1. 给tableData设置初始空数组
将tableData的初始state设为空数组,这样初始渲染时DataGrid的rows属性就不会是undefined,避免组件报错或异常显示:
const [tableData, setTableData] = useState([]); // 初始值设为空数组
2. (可选)添加加载状态提升用户体验
在数据请求过程中显示加载提示,让用户知道数据正在获取:
const [loading, setLoading] = useState(false); const getData = async () => { setLoading(true); // 请求开始时开启加载状态 try { const response = await axios.get('https://jsonplaceholder.typicode.com/users'); setTableData(response.data); } catch (err) { console.log(err); } finally { setLoading(false); // 请求结束(成功/失败)都关闭加载状态 } }
渲染时根据loading状态切换显示内容:
return ( <div className='table'> {loading ? ( <div>加载中...</div> // 可替换为自定义加载组件 ) : ( <DataGrid rows={tableData} columns={columnData.concat(activeColumn)} pageSize={pageSize} onPageSizeChange={(newPageSize) => setPageSize(newPageSize)} rowsPerPageOptions={[5, 10, 25, 50, 100]} checkboxSelection /> )} </div> )
3. 调整函数声明避免lint警告
原代码中getData定义在useEffect之后,虽然能运行,但React的ESLint规则可能会提示依赖缺失。可以把getData移到useEffect之前,或者用useCallback包裹:
const getData = useCallback(async () => { // 原getData逻辑 }, []); // 依赖为空数组,无需外部变量 useEffect(() => { getData(); }, [getData]); // 添加到依赖数组
修改后的完整代码
const Table = () => { const [pageSize, setPageSize] = useState(10); const [tableData, setTableData] = useState([]); // 初始空数组 const [loading, setLoading] = useState(false); const getData = async () => { setLoading(true); try { const response = await axios.get('https://jsonplaceholder.typicode.com/users'); setTableData(response.data); } catch (err) { console.log(err); } finally { setLoading(false); } } useEffect(() => { getData(); }, []) const activeColumn = [ {field: 'action', headerName: 'Action', width: 200, renderCell:() => { return( <div className='cellAction'> <div className='viewButton'>View</div> <div className='deleteButton'>Delete</div> </div> ) }} ] return ( <div className='table'> {loading ? ( <div>加载中...</div> ) : ( <DataGrid rows={tableData} columns={columnData.concat(activeColumn)} pageSize={pageSize} onPageSizeChange={(newPageSize) => setPageSize(newPageSize)} rowsPerPageOptions={[5, 10, 25, 50, 100]} checkboxSelection /> )} </div> ) }
关键说明
异步API请求本身需要时间,React组件无法在第一次渲染时就直接拿到请求结果。上述方案的核心是处理初始状态和优化用户体验,避免undefined导致的组件异常,同时让用户感知到数据加载过程。
内容的提问来源于stack exchange,提问作者deoxzy
相关产品推荐
相关产品推荐

