Cloudspace Design表格过滤与数据总数显示异常问题求助
Cloudscape Design表格数据总数统计与搜索功能冲突问题
问题背景
- 技术栈:后端NodeJS,前端React + Cloudscape Design
- 核心矛盾:
- 后端使用
filter方法过滤数据时,前端搜索功能正常,但表格数据总数统计异常 - 移除
filter方法后,总数显示正常,但搜索栏无法实现自由文本搜索
- 后端使用
- 当前状态:数据可正常获取并渲染,仅总数统计与搜索功能无法同时正常工作
后端现有代码
const takeAllUsers = async ()=>{ const res = await getUsers(); const users = res.data.getAllUsers.result.map((item: any) => { if (item.enabled) return {id: item.email, firstName: item.givenName, lastName: item.familyName, email: item.email, mobileNumber: item.phoneNumber, role: item.userRoles.toString(), profilePicture: item.profilePicture, status: item.enabled ? 'OK' : 'ERROR', customerId: item.customerId }; }).filter((i:any) => i); setUserLoading(false); setAllUsers(users); };
前端现有代码
import * as React from 'react'; import Layout from '../Layout/layout'; import Table from '../Customers/components/CustomTable'; import { SpaceBetween,TableProps, Link, StatusIndicator, StatusIndicatorProps, CollectionPreferencesProps} from '@cloudscape-design/components'; import UpdateUser from './components/UpdateUser'; import DeleteUser from './components/DeleteUser'; import InviteNewUser from './components/InviteNewUser'; import UsersType from '../../configs/types/Users'; import { userContext } from '../../UserContext/UserContext'; import { UserContextType } from '../../configs/types/UserContextType'; type InstanceState = 'OK' | 'ERROR'; const columnLabel = (column: string) => (sortState: TableProps.LabelData) => { const ascending = !sortState.descending; return `${column}, ${sortState.sorted ? `sorted ${ascending ? 'ascending' : 'descending'}` : 'not sorted'}.`; }; const stateToStatusIndicator: Record<InstanceState, StatusIndicatorProps> = { OK: { type: 'success', children: 'Active' }, ERROR: { type: 'error', children: 'Disabled' }, }; const visibleContentOptions: ReadonlyArray<CollectionPreferencesProps.VisibleContentOptionsGroup> = [ { label: 'Instance properties', options: [ { id: 'id', label: 'ID', editable: false, }, { id: 'firstName', label: 'First Name', }, { id: 'type', label: 'Type' }, { id: 'lastName', label: 'Last Name', }, { id: 'email', label: 'Email', }, { id: 'mobileNumber', label: 'Mobile Number', }, { id: 'officeAddress', label: 'Office Address', }, { id: 'role', label: 'Role', }, { id: 'profilePicture', label: 'Profile Picture', } ], }, ]; const Users: React.FC = () => { const { takeAllUsers,allUsers } = React.useContext(userContext) as UserContextType; const columnsConfig: TableProps.ColumnDefinition<UsersType>[] = [ { id: 'id', header: 'ID', cell: item => <Link href={`#${item.id}`}>{item.id}</Link>, ariaLabel: columnLabel('id'), sortingField: 'id', }, { id: 'firstName', header: 'Name', cell: item => item.firstName || '-', ariaLabel: columnLabel('Name'), sortingField: 'name', }, { id: 'lastName', header: 'Last Name', cell: item => item.lastName, ariaLabel: columnLabel('lastName'), sortingField: 'lastName' }, { id: 'email', header: 'Email', cell: item => item.email, ariaLabel: columnLabel('email'), sortingField: 'email' }, { id: 'mobileNumber', header: 'Mobile Number', cell: item => item.mobileNumber, ariaLabel: columnLabel('mobileNumber'), sortingField: 'mobileNumber' }, { id: 'officeAddress', header: 'Office Address', cell: item => item.officeAdress, ariaLabel: columnLabel('officeAdress'), sortingField: 'officeAdress' }, { id: 'role', header: 'Roles', cell: item => item.role, ariaLabel: columnLabel('role'), sortingField: 'role' }, { id: 'status', header: 'Status', cell: item => <StatusIndicator {...stateToStatusIndicator[item.status]} />, ariaLabel: columnLabel('state'), sortingField: 'status', }, { id: 'profilePicture', header: 'Image ID', cell: item => item.profilePicture, ariaLabel: columnLabel('imageId'), sortingField: 'imageId', } ]; const visibleContent=['id','firstName','lastName','email','mobileNumber','officeAddress','role','status','profilePicture']; const renderCustomerPage = () => { return ( <React.Fragment> <Table TableHeader={ <SpaceBetween direction="horizontal" size="xs"> <UpdateUser/> <DeleteUser/> <InviteNewUser/> </SpaceBetween> } columnsConfig={columnsConfig} data={allUsers} header="User" visibleContentOptions={visibleContentOptions} takeCustomerList={takeAllUsers} visibleContent={visibleContent} /> </React.Fragment> ); }; return ( <> <Layout header="Users" mainContent={renderCustomerPage()} items={[ { text: 'Home', href: '/admin' }, { text: 'Users', href: '/user'} ]} /> </> ); }; export default Users;
解决方案
1. 后端调整:分离全量原始数据与过滤后数据
修改takeAllUsers函数,同时保存全量用户数据和过滤后的有效用户数据,既满足搜索需求,又保证表格渲染的是过滤后的列表:
const takeAllUsers = async ()=>{ const res = await getUsers(); // 处理所有用户数据,保留原始字段用于后续搜索和过滤 const allRawUsers = res.data.getAllUsers.result.map((item: any) => ({ id: item.email, firstName: item.givenName, lastName: item.familyName, email: item.email, mobileNumber: item.phoneNumber, role: item.userRoles.toString(), profilePicture: item.profilePicture, status: item.enabled ? 'OK' : 'ERROR', customerId: item.customerId, enabled: item.enabled // 保留enabled字段用于前端过滤 })); // 过滤出启用状态的用户 const filteredUsers = allRawUsers.filter(user => user.enabled); setUserLoading(false); setAllUsers(filteredUsers); // 给表格渲染使用 setAllRawUsers(allRawUsers); // 保存全量数据用于搜索 };
注意:需要在你的
userContext中新增allRawUsers状态以及对应的setAllRawUsers方法。
2. 前端调整:基于全量数据实现搜索过滤
在Users组件中添加搜索状态和过滤逻辑,将搜索结果传递给表格:
const Users: React.FC = () => { const { takeAllUsers, allUsers, allRawUsers } = React.useContext(userContext) as UserContextType; const [searchQuery, setSearchQuery] = React.useState(''); // 基于搜索词过滤全量数据 const filteredData = React.useMemo(() => { if (!searchQuery.trim()) return allUsers; const lowerQuery = searchQuery.toLowerCase(); return allRawUsers.filter(user => user.firstName?.toLowerCase().includes(lowerQuery) || user.lastName?.toLowerCase().includes(lowerQuery) || user.email.toLowerCase().includes(lowerQuery) || user.mobileNumber?.includes(lowerQuery) || user.role.toLowerCase().includes(lowerQuery) ); }, [searchQuery, allRawUsers, allUsers]); // ... 保留原有columnsConfig、visibleContent等代码 const renderCustomerPage = () => { return ( <React.Fragment> {/* 添加搜索输入框 */} <input type="text" placeholder="搜索用户..." value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} style={{ marginBottom: '16px', padding: '8px' }} /> <Table TableHeader={ <SpaceBetween direction="horizontal" size="xs"> <UpdateUser/> <DeleteUser/> <InviteNewUser/> </SpaceBetween> } columnsConfig={columnsConfig} data={filteredData} // 传入过滤后的搜索结果 header="User" visibleContentOptions={visibleContentOptions} takeCustomerList={takeAllUsers} visibleContent={visibleContent} /> </React.Fragment> ); }; // ... 保留原有return代码 };
3. 验证效果
- 初始状态下,表格显示过滤后的启用用户,总数正确对应
allUsers的长度 - 输入搜索词时,表格会基于全量原始数据过滤,显示匹配结果,总数自动更新为当前搜索结果的数量
- 搜索功能和总数统计可同时正常工作
内容的提问来源于stack exchange,提问作者Onur
相关产品推荐
相关产品推荐

