React-TypeScript中Ant Design Table加载API数据不显示求助
React-TypeScript对接接口后Ant Design Table无法渲染数据的排查与解决
在React-TypeScript项目中对接get_customers接口,已解决CORS问题且能成功获取数据,但Ant Design Table组件始终无法正常渲染数据,页面显示空白。结合提供的代码和接口响应截图,问题主要集中在以下几点:
问题排查与修复
1. useEffect无限循环触发请求
当前useEffect未设置依赖数组,会在组件每次渲染时重复调用getCustomers,导致状态频繁更新,干扰Table渲染逻辑。
修复代码:
useEffect(() => { getCustomers(); }, []); // 添加空依赖数组,仅组件挂载时执行一次
2. 接口数据结构与Table要求不匹配
从接口响应可知,返回数据是包含data数组的对象(格式类似{data: [客户列表数据]}),但代码中直接将整个响应对象赋值给customersData,而AntD Table的dataSource必须接收数组类型数据。同时初始状态设为null也会导致判断逻辑异常。
修复代码:
// 初始化状态改为空数组并指定类型 const [customersData, setCustomersData] = useState<DataType[]>([]); // 接口请求后提取data数组 const getCustomers = () => { setLoading(true); return makeAPICall({ path: `get_customers`, method: "GET", }) .then((response) => { setCustomersData(response.data); // 提取数组数据 setLoading(false); console.log(response.data); }) .catch((err) => { setLoading(false); console.log(err); }); }
3. Table缺少唯一行标识
AntD Table需要每条数据有唯一标识,否则无法正常渲染行。可通过rowKey属性指定接口返回的唯一字段(如id)。
修复代码:
<Table columns={columns} dataSource={customersData} rowKey="id" />
4. 字段名大小写不匹配(可选)
DataType中定义的Avatar为大写开头,但接口返回的是小写avatar,会导致头像无法加载,需修正字段名与接口一致:
修复代码:
interface DataType { id: string; first_name: string; last_name: string; email: string; phone: string; ip_address: string; is_active: boolean; // 改为小写boolean,TypeScript中推荐小写 avatar: string; // 改为小写,匹配接口字段 } // 对应修改render中的引用 { title: 'First Name', dataIndex: 'first_name', key: 'first_name', render: (first_name, data) => { return ( <div> <img className='customers-avatar' src={data.avatar} alt="" /> {first_name} </div> ) }, }
修复后完整组件代码示例
import React, { useState, useEffect } from 'react'; import { Table, Space } from 'antd'; import { ColumnsType } from 'antd/es/table'; import { Link } from 'react-router-dom'; import SiderLayout from './path-to-SiderLayout'; // 替换为实际路径 interface DataType { id: string; first_name: string; last_name: string; email: string; phone: string; ip_address: string; is_active: boolean; avatar: string; } const columns: ColumnsType<DataType> = [ { title: 'First Name', dataIndex: 'first_name', key: 'first_name', render: (first_name, data) => { return ( <div> <img className='customers-avatar' src={data.avatar} alt="" /> {first_name} </div> ) }, }, { title: 'Last Name', dataIndex: 'last_name', key: 'last_name', }, { title: 'Email Address', dataIndex: 'email', key: 'email', }, { title: 'Phone Number', dataIndex: 'phone', key: 'phone', }, { title: 'Last Login', render: () => <p>April 2, 2022</p>, }, { title: '', key: 'action', render: () => ( <Space size="middle"> <Link to="/shipments" className='space-action'>Shipment</Link> <Link to="/" className='space-action-green'>Edit</Link> </Space> ), }, ]; const Customers: React.FC = () => { const [customersData, setCustomersData] = useState<DataType[]>([]); const [loading, setLoading] = useState(false); useEffect(() => { getCustomers(); }, []); const getCustomers = () => { setLoading(true); return makeAPICall({ path: `get_customers`, method: "GET", }) .then((response) => { setCustomersData(response.data); setLoading(false); console.log(response.data); }) .catch((err) => { setLoading(false); console.log(err); }); } return ( <SiderLayout> <div className="site-layout-background" style={{ padding: "40px 40px", minHeight: 710 }}> <button type='submit'>Add Customer +</button> {loading ? 'loading...' : ( <div> {customersData.length === 0 ? "No data" : <Table columns={columns} dataSource={customersData} rowKey="id" />} </div> )} </div> </SiderLayout> ) } export default Customers;
内容的提问来源于stack exchange,提问作者lakaJS
相关产品推荐
相关产品推荐

