【问题标题】:How does one supply a custom sort function for react table 7?如何为反应表 7 提供自定义排序功能?
【发布时间】:2021-01-03 17:36:32
【问题描述】:

documention for 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

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

那么如何提供一个 sortType 函数呢?

【问题讨论】:

    标签: react-table react-table-v7


    【解决方案1】:

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

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

    例如,修改快速入门的Define Columns,如下所示:

    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;
    }
    

    【讨论】:

    • 这非常适合对一行科学格式的数字进行排序(作为字符串返回渲染器)。这样我们就不管它们是否被列为字符串。
    • 唯一的解决方案,成功了。
    【解决方案2】:

    我也很难弄清楚这一点。这就是我的做法。它在 typescript 中,但如果你需要它在纯 js 中,只需删除所有类型。第一,这里是自定义排序。它将对字符串进行排序,并始终将 nulls/blanks/undefined 放在末尾。

    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);
    };
    

    有两点需要注意。

    1. 当返回值被定义为数字时,我不明白为什么 typescript 不喜欢它。我讨厌使用任何东西,但这行得通。
    2. react table 文档表明必须记住这一点。这不是,但它仍然有效。

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

    const sortTypes: Record<string, SortByFn<SomeObject>> = {
      customStringSort: customStringSort,
    };
    

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

    const {
      getTableProps,
      getTableBodyProps
      headerGroups,
      rows,
      prepareRow,
      } = useTable(
        {
          columns,
          data,
          sortTypes
        },
      useSortBy
    );
    

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

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

    希望这会有所帮助!

    --编辑:如果你想记住这个函数,这行得通。只需在适当的地方用 customStringSortMemo 替换 customStringSort。

    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]);
    

    【讨论】:

    • 关于 TS 和 any。你的类型放错地方了。它应该在参数之后。例如。 const customStringSort = (rowA: Row, rowB: Row, columnId: string, desc: boolean):number =&gt; {
    【解决方案3】:

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

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

    desc 标识排序的方向。即使提供了desc,排序函数也应该反转返回值。反应表会自动执行此操作。

    例如:

    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;
    })
    

    使用 sortType 的示例:

    const columns = [{       
            Header: ...
            accessor: ...
            sortType: /*sortType func goes here... */        
    }, ...]
    
    function MyTable(columns, data)
    {
     const { /*...*/ } = useTable({columns,data})
    }
    

    【讨论】:

    • 谢谢你,但我不知道你怎么能从 react-table 文档中得到这个答案......你怎么知道行会有一个你可以的对象类型的属性使用 id 属性访问?我还收到错误“无法在类组件中调用 React Hook “React.useMemo””,因为我在类组件中构建列,然后将它们传递给构建表的表示组件。有解决办法吗?
    • react-table.tanstack.com/docs/api/useSortBy 您需要将此函数传递给列。我仍在研究如何自己做,但是当我想出一些东西时我会发布。您不能在反应类组件中使用钩子。我会将与 react-table 相关的所有内容都放在功能组件中。所有文档都将它们放在同一个文件中,但我也在尝试进行一些分离。
    • @Tom,在您上面的排序功能中,我怀疑大多数人会使用rowA.values[id] 而不是rowA.original[id]。此外,&gt; 的常见语义可能返回 1 而不是 -1
    • @Eman4real,不需要内联你的函数。只需向sortType 提供比较函数的名称(例如compareNumericString),就像我在here 所做的那样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 2020-11-07
    • 2020-08-02
    相关资源
    最近更新 更多