React+Antd表格自定义筛选搜索调用API实现方法
在React+Antd中实现表格自定义筛选并调用后端API
核心思路
Antd表格的远程筛选需要手动维护筛选状态,在筛选条件变化时触发后端API请求,将接口返回的数据更新到表格数据源中。核心用到表格的onFilterChange事件、筛选状态管理,以及接口请求逻辑。
具体实现步骤
- 添加组件状态管理
在组件内部定义筛选参数、表格数据源、加载状态等核心状态:
import { useState, useEffect } from 'react'; import { Table, ColumnsType, Avatar } from 'antd'; import type { Product, Category } from './your-types'; // 替换成你的类型定义文件 const ProductTable = () => { // 存储各列的筛选值 const [filters, setFilters] = useState<Record<string, (string | number)[]>>({}); // 表格数据源 const [dataSource, setDataSource] = useState<Product[]>([]); // 请求加载状态 const [loading, setLoading] = useState(false); // 分类选项列表 const [categories, setCategories] = useState<Category[]>([]); // 组件挂载时初始化分类和表格数据 useEffect(() => { fetchCategories(); fetchTableData(); }, []);
- 封装接口请求函数
编写获取分类列表和表格数据的函数,将筛选参数按后端要求格式传递:
// 获取分类选项列表 const fetchCategories = async () => { try { const res = await fetch('/api/categories'); // 替换成你的分类接口地址 const data = await res.json(); setCategories(data); } catch (err) { console.error('获取分类失败:', err); } }; // 获取表格数据,携带筛选参数 const fetchTableData = async () => { setLoading(true); try { // 转换筛选参数为后端需要的格式 const params = new URLSearchParams(); // 处理分类筛选参数 if (filters.categories?.length) { params.append('categoryIds', filters.categories.join(',')); } // 其他列的筛选参数可类似处理,比如名称搜索 // if (filters.name?.length) params.append('name', filters.name[0]); const res = await fetch(`/api/products?${params.toString()}`); // 替换成你的商品列表接口 const data = await res.json(); setDataSource(data); } catch (err) { console.error('获取表格数据失败:', err); } finally { setLoading(false); } };
- 修改表格列配置
对需要远程筛选的列(比如分类列)添加filterMode: 'remote'标记,优化渲染逻辑:
const columns: ColumnsType<Product> = [ { title: '名称', dataIndex: 'name', key: 'name', render: (name, record) => ( <div className="flex items-center"> <Avatar src={record.avatar}>{name[0].toUpperCase()}</Avatar> <span style={{ marginLeft: 10 }} className="whitespace-nowrap"> <a title="查看&编辑" href={`/product/${record.id}`}> {name} </a> </span> </div> ), // 若名称列也需远程搜索,可添加以下配置 // filterMode: 'remote', // filterSearch: true, }, { title: '简介', dataIndex: 'about', key: 'about', render: (about: string) => <p className="text-ellipsis line-clamp-2">{about}</p>, width: 400, }, { title: '分类', dataIndex: 'categories', key: 'categories', filterMode: 'remote', // 标记为远程筛选,关闭前端过滤 filterSearch: true, filters: categories.map((category: Category) => ({ text: category.name, value: category.id })), render: (categoryIds: number[]) => { if (!categoryIds?.length) return '-'; return categoryIds.map(id => { const category = categories.find(c => c.id === id); return ( <span key={id} className="mr-2 px-2 py-1 bg-gray-100 rounded"> {category?.name || id} </span> ); }); }, }, { title: '地址', dataIndex: 'contract_addresses', key: 'address', render: addresses => addresses?.[0] || '-' }, ];
- 配置Table组件
绑定筛选变化事件,传入状态和列配置:
// 监听筛选条件变化,触发数据请求 const handleFilterChange = (newFilters: Record<string, (string | number)[]>) => { setFilters(newFilters); fetchTableData(); }; return ( <Table columns={columns} dataSource={dataSource} rowKey="id" // 替换成你的数据唯一标识字段 loading={loading} onFilterChange={handleFilterChange} // 如需分页,可添加以下配置,将分页参数传给后端 // pagination={{ // current: page, // pageSize: pageSize, // onChange: (newPage, newPageSize) => { // setPage(newPage); // setPageSize(newPageSize); // fetchTableData(); // }, // }} /> ); }; export default ProductTable;
关键说明
filterMode: 'remote':告知Antd该列使用远程筛选,跳过前端数据过滤逻辑onFilterChange:每次筛选条件变化时,同步更新筛选状态并触发后端请求- 参数转换:根据后端接口要求,将Antd返回的筛选格式转换成接口可识别的参数(如逗号拼接、JSON字符串等)
- 加载状态:请求过程中显示加载动画,提升用户体验
内容的提问来源于stack exchange,提问作者vantrong
相关产品推荐
相关产品推荐

