如何为反应表 7 提供自定义排序功能?

Tom*_*Tom 3 react-table react-table-v7

useSortBy sortType 属性的文档说:

sortType: String | Function(rowA: <Row>, rowB: <Row>, columnId: String, desc: Bool)

    Used to compare 2 rows of data and order them correctly.
    If a function is passed, it must be memoized. The sortType function should return -1 if rowA is larger, and 1 if rowB is larger. react-table will take care of the rest.
    String options: basic, datetime, alphanumeric. Defaults to alphanumeric.
    The resolved function from the this string/function will be used to sort the this column's data.
        If a string is passed, the function with that name located on either the custom sortTypes option or the built-in sorting types object will be used.
        If a function is passed, it will be used.
    For more information on sort types, see Sorting
Run Code Online (Sandbox Code Playgroud)

但没有完全解释如何使用它。

那么如何提供 sortType 函数呢?

Tom*_*Tom 11

sortType 函数的参数是:(rowA, rowB, columnId, desc)

columnId 标识行按哪一列排序,因此允许获取单元格值。

desc标识排序的方向。即使desc提供,排序功能应该不是反向的返回值。react table 会自动执行此操作。

例如:

sortType: React.useMemo((rowA, rowB, id, desc) => {
       if (rowA.original[id] > rowB.original[id]) return -1; 
       if (rowB.original[id] > rowA.original[id]) return 1;
        return 0;
})
Run Code Online (Sandbox Code Playgroud)

在何处使用 sortType 的示例:

const columns = [{       
        Header: ...
        accessor: ...
        sortType: /*sortType func goes here... */        
}, ...]

function MyTable(columns, data)
{
 const { /*...*/ } = useTable({columns,data})
}
Run Code Online (Sandbox Code Playgroud)


Ken*_*Lin 9

根据您的文档引文, sortType 是Column option

传递给选项的任何Column对象都支持以下选项columnsuseTable()

例如,修改快速入门的定义列,如下所示:

const columns = React.useMemo(
  () => [
    {
      Header: 'Column 1',
      accessor: 'col1', // accessor is the "key" in the data
    },
    {
      Header: 'Column 2',
      accessor: 'col2',
      sortType: compareNumericString // custom function
    },
  ],
  []
)

function compareNumericString(rowA, rowB, id, desc) {
    let a = Number.parseFloat(rowA.values[id]);
    let b = Number.parseFloat(rowB.values[id]);
    if (Number.isNaN(a)) {  // Blanks and non-numeric strings to bottom
        a = desc ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY;
    }
    if (Number.isNaN(b)) {
        b = desc ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY;
    }
    if (a > b) return 1; 
    if (a < b) return -1;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)


Roo*_*Eat 5

我在解决这个问题时也遇到了很大的麻烦。我是这样做的。它是用打字稿写的,但如果你需要用纯 js 写的,只需删除所有打字即可。第一,这里是自定义排序。它将对字符串进行排序,并始终将空值/空白/未定义放在末尾。

const customStringSort: any = (rowA: Row, rowB: Row, columnId: string, desc: boolean) => {
  const defaultVal = desc ? 'AAAAAAAAAAAA' : 'ZZZZZZZZ';
  return (rowA.values[columnId] ?? defaultVal)
    .localeCompare(rowB.values[columnId] ?? defaultVal);
};
Run Code Online (Sandbox Code Playgroud)

对此有两点需要注意。

  1. 我不明白为什么打字稿不喜欢将返回值定义为数字。我讨厌使用任何一个,但这有效。
  2. 反应表文档表明必须记住这一点。这不是,但它仍然有效。

接下来,您必须将此函数添加到 sortTypes 中。

const sortTypes: Record<string, SortByFn<SomeObject>> = {
  customStringSort: customStringSort,
};
Run Code Online (Sandbox Code Playgroud)

接下来,将 sortType 添加到 useTable 实例。

const {
  getTableProps,
  getTableBodyProps
  headerGroups,
  rows,
  prepareRow,
  } = useTable(
    {
      columns,
      data,
      sortTypes
    },
  useSortBy
);
Run Code Online (Sandbox Code Playgroud)

现在您可以将自定义函数添加到列定义中。

const columns: Column<SomeObject>[] = React.useMemo(() => 
  [
    { accessor: 'someColumnID', Header: 'Some Column', sortType:'customStringSort' },
  ],
  [],
);
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!

--编辑:如果你想记住该函数,这是可行的。只需在适当的情况下将 customStringSort 替换为 customStringSortMemo 即可。

const customStringSort: any = React.useCallback((rowA: Row, rowB: Row, columnId: string, desc: boolean) => 
  {
  const defaultVal = desc ? 'AAAAAAAAAAAA' : 'ZZZZZZZZ';
  return (rowA.values[columnId] ?? defaultVal).localeCompare(rowB.values[columnId] ?? defaultVal);
  },
[]);
    
const customStringSortMemo = React.useMemo(() => customStringSort[customStringSort]);
Run Code Online (Sandbox Code Playgroud)