我是 ReactJS 新手。我创建了一个包含 2 列的表。这是我的代码:
import React, { useState, useEffect } from 'react'
import { getUsers } from '../../services/userService'
import { useNavigate } from 'react-router-dom'
import Pagination from '@mui/material/Pagination'
const Table = () => {
const navigate = useNavigate()
const [users, setUsers] = useState([]);
const [currentUsers, setCurrentUsers] = useState([]);
const [search, setSearch] = useState('');
const [sorting, setSorting] = useState({ key: "name", ascending: true });
const pageItemCount = 15
const [pageCount, setPageCount] = useState(0)
const [currentPage, setCurrentPage] = useState(1)
useEffect(async () => {
try {
const response = await getUsers(search);
setUsers(response.data.users);
setPageCount(Math.ceil(response.data.users.length / pageItemCount))
setCurrentUsers(response.data.users.slice(0, pageItemCount))
} catch (error) { }
}, [search]);
/**************************************** */
useEffect(() => {
const currentUsersCopy = [...currentUsers];
const sortedCurrentUsers = currentUsersCopy.sort((a, b) => {
return a[sorting.key].localeCompare(b[sorting.key]);
});
setCurrentUsers(
sorting.ascending ? sortedCurrentUsers : sortedCurrentUsers.reverse()
);
}, [currentUsers, sorting]);
/*************************************** */
function applySorting(key, ascending) {
setSorting({ key: key, ascending: ascending });
}
/************************************** */
const changePage = (i) => {
setCurrentPage(i)
const startItem = ((i - 1) * pageItemCount) + 1
setCurrentUsers(users.slice(startItem - 1, (pageItemCount * i)))
}
const handleChange = (event, value) => {
changePage(value);
}
return (
<div dir='rtl' className='bg-background mt-10 px-5 rd1200:px-30 overflow-auto'>
<div className='flex flex-wrap justify-between items-center'>
<div>
<svg className='relative top-10 right-3' width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 5H20" stroke="#79899e" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M14 8H17" stroke="#79899e" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M21 11.5C21 16.75 16.75 21 11.5 21C6.25 21 2 16.75 2 11.5C2 6.25 6.25 2 11.5 2" stroke="#79899e" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M22 22L20 20" stroke="#79899e" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
<input type='text' className='my-3 py-2 pl-3 pr-10 text-sm text-text-secondary shadow-sm focus:ring-2 ring-text-secondary rounded-md w-full rd500:w-120' placeholder='search ..' onChange={(e) => setSearch(e.target.value)} value={search} />
</div>
<div className="flex justify-center">
<select className="form-select form-select-sm
my-3 py-2 pl-15 pr-2 text-sm text-text-secondary shadow-sm rounded-md w-full
focus:ring-2 focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none " aria-label=".form-select-sm example">
<option selected value="1" onClick={() => navigate('/')}>users</option>
<option value="2" onClick={() => navigate('/ext')}>other users</option>
</select>
</div>
</div>
<table className='w-full border-separate rounded-md'>
<thead>
<tr className='bg-text-secondary text-white shadow-sm text-center'>
<th className='p-2' onClick={() => applySorting('name', !sorting.ascending)}>name</th>
<th className='p-2' onClick={() => applySorting('name', !sorting.ascending)}>phone</th>
</tr>
</thead>
<tbody>
{currentUsers.map((item, index) =>
<tr key={item.id} className={index % 2 === 0 ? 'bg-white shadow-sm text-center' : 'bg-text bg-opacity-5 shadow-sm text-center'}>
<td className='text-text text-sm p-2'>{item.name}</td>
<td className='text-text text-sm p-2'>{item.phone}</td>
</tr>
)}
</tbody>
</table>
<Pagination className="mt-2 pb-20" dir='ltr' page={currentPage} count={pageCount} onChange={handleChange} variant="outlined" shape="rounded" />
</div>
)
}
export default Table
我试图通过单击每个列标题来对该表进行排序。我尝试应用 link1 中建议的解决方案和 link2 ,但我还没有成功。我怎样才能做到这一点?
已编辑:我编辑了代码并添加了表格的完整代码。
最佳答案
I'm trying to sort this table by clicking on each column header.
实现此类功能的可能解决方案之一是存储排序的当前状态。为此,我们可以使用 useState
钩子(Hook)
const [sorting, setSorting] = useState({ field: 'name', ascending: false })
如您所见,useState
函数接受默认值。在我们的例子中,默认值将是排序默认状态。 field
属性告诉我们要按哪一列进行排序,而 ascending
属性则告诉我们应该按照什么顺序排序。
接下来,我们需要为列的每个标题设置事件处理程序。
<tr className='bg-text-secondary text-white shadow-sm text-center'>
<th className='p-2' onClick={() => applySorting('name', !sorting.ascending)}>name</th>
<th className='p-2' onClick={() => applySorting('phone', !sorting.ascending)}>phone</th>
</tr>
通过单击列标题,我们调用函数 applySorting
来说明应对哪一列进行排序。
function applySorting(key, ascending) {
setSorting({ key: key, ascending: ascending });
}
我们需要做的最后一件事是对存储在 currentUsers
变量中的数据进行排序。
这部分代码有点棘手,因为它使用了 useEffect
钩子(Hook)。您可以阅读React documentation了解它是如何工作的。
假设每次您更改排序变量的当前状态时,React 都会调用此函数。
useEffect(() => {
// Copy array to prevent data mutation
const currentUsersCopy = [...currentUsers];
// Apply sorting
const sortedCurrentUsers = currentUsersCopy.sort((a, b) => {
return a[sorting.key].localeCompare(b[sorting.key]);
});
// Replace currentUsers with sorted currentUsers
setCurrentUsers(
// Decide either currentUsers sorted by ascending or descending order
sorting.ascending ? sortedCurrentUsers : sortedCurrentUsers.reverse()
);
}, [currentUsers, sorting]);
我在codesandbox上创建了这个示例,您可以在其中尝试这种方法。 Link to working example
我希望你喜欢学习 React!
关于reactjs - 通过单击列标题对表格进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72254047/