React.js请求API渲染动态表格时data未定义报错的问题排查
报错原因定位
- 直接触发
data is not defined报错的核心原因是作用域不连通:renderTableData是定义在模块顶层的独立函数,自身的作用域内没有声明data变量。代码里用到的data是在CreateTestcaseStep2组件内部通过useFetchHook解构得到的,两个作用域完全隔离,renderTableData执行时找不到data,自然抛出未定义的错误。 - 代码中还存在几个会引发后续异常的隐藏问题:
useFetchHook里把data的初始值设置为空字符串'',但接口返回的是对象列表,初始渲染阶段就调用数组方法map会直接抛出类型错误- 直接把async函数作为
useEffect的回调传入,不符合React的语法要求(useEffect的回调需要返回同步的清理函数,不能返回Promise),会触发开发环境的警告,甚至导致副作用重复执行、接口重复请求 - 没有对
loading状态做判断,数据还在请求中时就直接渲染表格,容易出现空值、结构不匹配的异常
修正方案
- 打通函数和数据的作用域:不要让
renderTableData直接引用外层组件的变量,改成把data作为入参传入函数,明确函数的依赖关系 - 调整
useFetch的初始数据类型:把data的初始值从空字符串改为空数组[],和接口返回的列表结构对齐 - 修正
useEffect的取数写法:在useEffect的同步回调内部定义独立的async取数函数,再执行调用,避免直接把async函数传给useEffect - 增加加载状态判断:等
loading变为false、数据加载完成后再渲染表格内容,同时加接口请求的异常捕获,避免请求失败时页面崩溃
修正后的代码参考:
import React, { useEffect, useState } from "react"; // 调整renderTableData,接收data作为入参 function renderTableData(data) { // 兜底判断:确保data是数组再执行map if (!Array.isArray(data)) return null return data.map((student) => { const { config, text, source_link, tab_type } = student return ( <tr key={config}> <td>{config}</td> <td>{text}</td> <td>{source_link}</td> <td>{tab_type}</td> </tr> ) }) } const useFetch = (url) => { // 初始值改为空数组,匹配列表结构 const [data, setData] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { // 在useEffect的同步回调内部定义async取数函数 const fetchData = async () => { try { const response = await fetch(url, { method: 'GET' }) const result = await response.json() setData(result) } catch (err) { console.error('接口请求失败', err) } finally { setLoading(false) } } fetchData() }, [url]); return { data, loading }; } export default function CreateTestcaseStep2() { // 替换为实际的接口地址 const { data, loading } = useFetch(ENPOINT_URL_GOES_HERE) return ( <div> <h1 id='title'>React动态表格</h1> {loading ? <p>数据加载中...</p> : ( <table id='students'> <tbody> {/* 把data作为参数传给renderTableData */} {renderTableData(data)} </tbody> </table> )} </div> ); }
内容的提问来源于stack exchange,提问作者Mahesh
相关产品推荐
相关产品推荐

