所以,这是我前端的代码片段。
{store.results.data.map( result =>
<ResultItem
key={result.id}
title={result.title}
description={result.description}
start_date={result.start_date}
end_date={result.end_date}
vendor_name={result.vendor.name}
buyer_name={result.buyer.name}
preview_file={result.preview_file}
status={result.status}
/>
)}
基本上,我将Redux商店中的所有数据映射到ResultItems。我希望能够按ResultItems
,title
,description
,start_date
,end_date
和{{}等不同属性对vendor_name
所有buyer_name
进行排序{1}}。
关于如何做到这一点的任何想法?
答案 0 :(得分:1)
首先,您应该知道几乎无法处理反应组件 - 这包括对它们进行排序。
其次,如果您有一个数组(比如arr
)并且在其上调用.sort()
方法,则数组将按就地排序,即{{ 1}}将被修改。
现在,您的问题的时间。在指出here时,您希望实现动态排序。这需要一些自定义compareFunction 知道如何根据对象比较对象。这是一个例子:
arr
以下是您的代码的外观:
arr = [
{
num: 1,
text: 'z',
},
{
num: 2,
text: 'y'
},
{
num: 3,
text: 'x'
},
];
const ASC = 'ascending';
const DSC = 'descending';
function sortByNum(a, b, order = ASC) {
const diff = a.num - b.num;
if (order === ASC) {
return diff;
}
return -1 * diff;
}
function sortByText(a, b, order = ASC) {
const diff = a.text.toLowerCase().localeCompare(b.text.toLowerCase());
if (order === ASC) {
return diff;
}
return -1 * diff;
}
console.log(arr.sort((a, b) => sortByNum(a, b, DSC)))
console.log(arr.sort((a, b) => sortByText(a, b, ASC)))
答案 1 :(得分:0)
您必须在执行地图部分之前对数据进行排序。例如,想象你想按id排序:
{store.results.data.sort((a, b) => a.id - b.id).map( result =>
<ResultItem key={result.id}
title={result.title}
description={result.description}
start_date={result.start_date}
end_date={result.end_date}
vendor_name={result.vendor.name}
buyer_name={result.buyer.name}
preview_file={result.preview_file}
status={result.status}
/>)}
答案 2 :(得分:0)
Lodash库可以达到这个目的。
{_.sortBy(store.results.data, ['status', 'start_date']).map( result =>
<ResultItem key={result.id}
title={result.title}
description={result.description}
start_date={result.start_date}
end_date={result.end_date}
vendor_name={result.vendor.name}
buyer_name={result.buyer.name}
preview_file={result.preview_file}
status={result.status}
/&GT;)}
您可以在['status','start_date',...]中提供要排序的多个字段。
答案 3 :(得分:0)
如果您使用select来选择要排序的字段,则可以创建以下内容:
<select onChange={(e) => {
props.dispatch(sortMyArray(e.target.value))
}}>
<option value="start_date">Start Date</option>
<option value="title">Title</option>
<option value="description">description</option>
</select>
并在sort方法sortMyArray中,你可以这样做:
export default sortMyArray(sortBy){
return myArray.sort((a, b) => {
if (sortBy === 'start_date') {
return a.start_date < b.start_date ? 1 : -1;
}
});
};
答案 4 :(得分:0)
我将创建一个Sort组件并像这样包装结果项:
<Sort by='title'>
{store.results.data.map( result =>
<ResultItem
key={result.id}
title={result.title}
description={result.description}
start_date={result.start_date}
end_date={result.end_date}
vendor_name={result.vendor.name}
buyer_name={result.buyer.name}
preview_file={result.preview_file}
status={result.status}
/>
)}
</Sort>
// Note: The 'by' prop passed into <Sort> in my example is hardcoded by you can grab it from redux or set it when user selects something from a list. Also you can pass another prop to indicate whether to sort by ascending or descending order etc
然后,在Sort组件中,您可以访问诸如React.Children.toArray
之类的结果项数组,并对数组使用sort方法,并将sort方法传递给'compare'函数。
// Sort.js
import React from 'react';
// Compare function needed by the Sort component
const compare =(a, b) => {
// you can access the relevant property like this a.props[by]
// depending whether you are sorting by tilte or year, you can write a compare function here,
}
const Sort= ({children, by})=> {
If (!by) {
// If no 'sort by property' provided, return original list
return children
}
return React.Children.toArray(children).sort(compare)
}
上面的主要优点是您可以在其他任何地方使用Sort组件,并且可以使排序逻辑与映射到初始结果上完全分开。
答案 5 :(得分:0)
我用这个组件代码得到了这个:
/* eslint-disable react/jsx-no-useless-fragment */
/* eslint-disable @typescript-eslint/no-explicit-any */
import React from 'react';
import './Sort.module.scss';
export interface SortProps {
children: React.ReactNode;
childType: string;
by?: any;
keyWith?: string;
}
// thx: https://stackoverflow.com/a/55996695/6200791
// thx: https://frontarm.com/james-k-nelson/passing-data-props-children/
// -------------------
export const Sort: React.FC<SortProps> = ({ children, childType, by, keyWith = "id" }) => {
// ##################################################################################
// # COMPARISON FUNCTION
// ##################################################################################
const compare = (aRaw: any, bRaw: any): any => {
const a = aRaw.props[childType];
const b = bRaw.props[childType];
// Compare function needed by the Sort component
// you can access the relevant property like this a.props[by]
// depending whether you are sorting by tilte or year, you can write a compare function here,
if (!!a && !!b) {
switch (by) {
case "createdAt":
return b[by] > a[by] ? 1 : -1;
break;
case "description":
return a[by].localeCompare(b[by]);
break;
}
}
}
// ##################################################################################
// # /end COMPARISON FN
// ##################################################################################
if (!children) {
return (<></>);
}
if (!by) {
// If no 'sort by property' provided, return original list
return (<>{children}</>);
} else {
// trying to workaround error: Each child in a list should have a unique "key" prop
const elements: any[] = React.Children.toArray(children);
const keyed: any[] = elements
.sort(compare)
.map((child, newIdx) => {
return React.cloneElement(child, { key: (child as any)[keyWith], idx: newIdx });
});
return (<>{keyed}</>);
}
}
export default Sort;
然后我使用如下(故事书故事):
import React from 'react';
import Sort from './Sort';
type CartModified = {
description: string;
id: number;
name: string;
createdAt: string;
}
export default {
component: Sort,
title: 'Sort',
};
const carts = [
{ id: 2, name: "2nd", createdAt: "2021-04-23T23:27:51.943Z", description: "d" },
{ id: 3, name: "3rd", createdAt: "2021-05-23T23:27:51.943Z", description: "b" },
{ id: 1, name: "1st", createdAt: "2021-03-23T23:27:51.943Z", description: "c" },
{ id: 4, name: "4th", createdAt: "2021-06-23T23:27:51.943Z", description: "a" },
] as CartModified[];
const TestItem: React.FC<{ c: CartModified }> = ({ c }) => {
return <div>
{c.name} # {c.id} - {c.createdAt} ({c.description})
</div>;
}
// -------------------
export const withSortByCreatedAt = () => {
return <Sort by="createdAt" childType="c" >
{carts.map((c) => !c ? null : (
<TestItem
key={c.id}
c={c}/>
))}
</Sort>;
};
// -------------------
export const withSortByCategory = () => {
return <Sort by="description" childType="c" >
{carts.map((c) => !c ? null : (
<TestItem
key={c.id}
c={c}/>
))}
</Sort>;
};