React+MUI表格排序报错‘Data is not iterable’求助
解决React + MUI表格排序时的"Data is not iterable"错误
问题根源
你遇到的Data is not iterable错误,核心原因是将API返回的整个对象存入了data状态,而非其中的results数组。RandomUser API返回的结构是{ results: [...用户数组...], info: ... },当你在sorting函数中尝试用[...data]展开这个对象时,对象不是可迭代类型,因此抛出错误。
具体修复步骤
1. 修正API数据的存储逻辑
在useEffect的fetch回调中,仅将data.results存入状态:
useEffect(()=>{ fetch('https://randomuser.me/api/?results=30') .then((response) => response.json()) .then((apiData) => { setData(apiData.results); // 存储用户数组而非整个API响应对象 }); }, []);
2. 修复排序函数逻辑
现在data是用户数组,[...data]可正常展开。同时针对嵌套属性(姓名、城市)调整排序逻辑:
const sorting=(col)=>{ if(order==='asc'){ let sorted; // 处理嵌套属性排序 if(col === 'fullname'){ sorted = [...data].sort((a,b) => { const nameA = `${a.name.first} ${a.name.last}`.toLowerCase(); const nameB = `${b.name.first} ${b.name.last}`.toLowerCase(); return nameA > nameB ? 1 : -1; }); } else if(col === 'city'){ sorted = [...data].sort((a,b) => { const cityA = a.location.city.toLowerCase(); const cityB = b.location.city.toLowerCase(); return cityA > cityB ? 1 : -1; }); } else { sorted = [...data].sort((a,b) => a[col].toLowerCase() > b[col].toLowerCase() ? 1 : -1 ); } setData(sorted); setOrder('dsc'); } else if(order==='dsc'){ // 用else if避免同时执行两个分支 let sorted; if(col === 'fullname'){ sorted = [...data].sort((a,b) => { const nameA = `${a.name.first} ${a.name.last}`.toLowerCase(); const nameB = `${b.name.first} ${b.name.last}`.toLowerCase(); return nameA < nameB ? 1 : -1; }); } else if(col === 'city'){ sorted = [...data].sort((a,b) => { const cityA = a.location.city.toLowerCase(); const cityB = b.location.city.toLowerCase(); return cityA < cityB ? 1 : -1; }); } else { sorted = [...data].sort((a,b) => a[col].toLowerCase() < b[col].toLowerCase() ? 1 : -1 ); } setData(sorted); setOrder('asc'); } }
3. 完善表头的排序绑定
给所有列添加点击事件,并通过TableSortLabel展示当前排序方向:
<TableHead> <TableRow sx={{'& .MuiTableCell-root':{backgroundColor:"rgb(120, 169, 233)", border: "1px solid white", color: 'white'}}} <TableCell onClick={()=>sorting("fullname")} align="center"> <TableSortLabel active={true} direction={order}>Fullname</TableSortLabel> </TableCell> <TableCell onClick={()=>sorting("email")} align="center"> <TableSortLabel active={true} direction={order}>E-Mail</TableSortLabel> </TableCell> <TableCell onClick={()=>sorting("nat")} align="center"> <TableSortLabel active={true} direction={order}>Nationality</TableSortLabel> </TableCell> <TableCell onClick={()=>sorting("city")} align="center"> <TableSortLabel active={true} direction={order}>City</TableSortLabel> </TableCell> </TableRow> </TableHead>
4. 修复分页组件的计数逻辑
TablePagination的count应使用data.length而非空数组rows.length:
<TablePagination rowsPerPageOptions={[10, 25, 100]} component="div" count={data.length} // 改为用户数组的长度 rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage} onRowsPerPageChange={handleChangeRowsPerPage} />
5. 优化表格渲染逻辑
初始data是空数组,可直接调用slice(),无需可选链:
{data.slice(page*rowsPerPage, page*rowsPerPage+rowsPerPage).filter((val)=>{ if(searchTerm=== "") return val; const term = searchTerm.toLowerCase(); return val.nat.toLowerCase().includes(term) || val.email.toLowerCase().includes(term) || val.location.city.toLowerCase().includes(term); }).map((user,index) => ( <TableRow key={index} sx={{'& .MuiTableCell-root':{backgroundColor: 'rgba(54, 96, 129, 0.241)', height: '3rem'}}} <TableCell align="center" component="th" scope="row"> {`${user.name.first} ${user.name.last}`} </TableCell> <TableCell align="center">{user.email}</TableCell> <TableCell align="center">{user.nat}</TableCell> <TableCell align="center">{user.location.city}</TableCell> </TableRow> ))}
额外优化建议
- 将排序状态拆分为
orderBy(当前排序列)和orderDirection(升序/降序),避免切换排序时所有列同步变化 - 提取排序逻辑为独立函数,提升代码可读性和复用性
内容的提问来源于stack exchange,提问作者Mavix87
相关产品推荐
相关产品推荐

