我正在尝试使用Reaction中的自定义排序功能对数据进行排序。遗憾的是,该函数仅在记录为大写字母或小写字母时对项目进行排序。它不能正确地对大小写混合的数据进行排序。这是现场直播的link
以下是代码
const useSortableData = (items, config = null) => {
const [sortConfig, setSortConfig] = React.useState(config);
const sortedItems = React.useMemo(() => {
let sortableItems = [...items];
if (sortConfig !== null) {
sortableItems.sort((a, b) => {
if (a[sortConfig.key] < b[sortConfig.key]) {
return sortConfig.direction === 'ascending' ? -1 : 1;
}
if (a[sortConfig.key] > b[sortConfig.key]) {
return sortConfig.direction === 'ascending' ? 1 : -1;
}
return 0;
});
}
return sortableItems;
}, [items, sortConfig]);
const requestSort = (key) => {
let direction = 'ascending';
if (
sortConfig &&
sortConfig.key === key &&
sortConfig.direction === 'ascending'
) {
direction = 'descending';
}
setSortConfig({ key, direction });
};
return { items: sortedItems, requestSort, sortConfig };
};
const ProductTable = (props) => {
const { items, requestSort, sortConfig } = useSortableData(props.products);
const getClassNamesFor = (name) => {
if (!sortConfig) {
return;
}
return sortConfig.key === name ? sortConfig.direction : undefined;
};
return (
<table>
<caption>Products</caption>
<thead>
<tr>
<th>
<button
type="button"
onClick={() => requestSort('name')}
className={getClassNamesFor('name')}
>
Name
</button>
</th>
<th>
<button
type="button"
onClick={() => requestSort('price')}
className={getClassNamesFor('price')}
>
Price
</button>
</th>
<th>
<button
type="button"
onClick={() => requestSort('stock')}
className={getClassNamesFor('stock')}
>
In Stock
</button>
</th>
</tr>
</thead>
<tbody>
{items.map((item) => (
<tr key={item.id}>
<td>{item.name}</td>
<td>${item.price}</td>
<td>{item.stock}</td>
</tr>
))}
</tbody>
</table>
);
};
function App() {
return (
<div className="App">
<ProductTable
products={[
{ id: 1, name: 'Cheese', price: 4.9, stock: 20 },
{ id: 2, name: 'milk', price: 1.9, stock: 32 },
{ id: 3, name: 'Yoghurt', price: 2.4, stock: 12 },
{ id: 4, name: 'Heavy Cream', price: 3.9, stock: 9 },
{ id: 5, name: 'butter', price: 0.9, stock: 99 },
{ id: 6, name: 'Sour Cream ', price: 2.9, stock: 86 },
{ id: 7, name: 'Fancy French Cheese 🇫🇷', price: 99, stock: 12 },
]}
/>
</div>
);
}
ReactDOM.createRoot(document.querySelector("#root")).render(<App />);
body {
font-family: 'open sans', sans-serif;
font-size: 16px;
}
table {
width: 100%;
border-collapse: collapse;
}
thead th {
text-align: left;
border-bottom: 2px solid black;
}
thead button {
border: 0;
border-radius: none;
font-family: inherit;
font-weight: 700;
font-size: inherit;
padding: 0.5em;
margin-bottom: 1px;
}
thead button.ascending::after {
content: '👇';
display: inline-block;
margin-left: 1em;
}
thead button.descending::after {
content: '☝️';
display: inline-block;
margin-left: 1em;
}
tbody td {
padding: 0.5em;
border-bottom: 1px solid #ccc;
}
tbody tr:hover {
background-color: #eee;
}
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>
我尝试将a和b从useSortable改为小写,但由于有带数字的价格列,因此出错。
不管区分大小写,我可以做些什么才能使它工作。
3条答案
按热度按时间ifsvaxew1#
我认为对不同的类型有不同的分类功能是合理的。我建议为字符串类型和数字类型设置一个排序函数,并根据列类型使用它。这样一来,代码就变得更清晰、更易维护了。
r8xiu3jd2#
使用
a[sortConfig.key] < b[sortConfig.key]
比较2个字符串将导致基于字符代码点而不是字符内容进行比较。根据内容比较两个字符串的一种简单方法是使用localeCompare()
。如果您确信
a[sortConfig.key]
和b[sortConfig.key]
将始终返回字符串,则可以return a[sortConfig.key].localeCompare(b[sortConfig.key])
而无需任何额外检查。但是,在您的场景中,它们也可以表示
price
或stock
,它们都是数字,因此没有方法localeCompare()
。因此,我们应该事先检查这两个值是否都是字符串。我个人不喜欢输入检查,因为JavaScript是一种简单的类型语言。我通常会检查我需要的方法是否可用。
假设定义了以下帮助器:
您可以按以下方式对收藏进行排序:
或者,如果您更愿意使用类型检查,则可以使用
typeof value === "string"
而不是hasMethod(value, "localeCompare")
。v64noz0r3#
您可以检查类型,例如: