javascript React table类不首先将字符串排序为数字

6ojccjat  于 2023-04-19  发布在  Java
关注(0)|答案(1)|浏览(95)

一个名为GenericTable的表的泛型类已经使用react-table作为基础作为react组件:

import React from 'react'
import { translate } from '../../Translations'
import { toId } from '../../../utility/common'
import { useTable, useSortBy, usePagination, useFilters, useGlobalFilter } from 'react-table'

function Table({ id, tableConfig, columns, data, fileName, currPage, filterValue, sortArray, onPageChange, onFilterChange, onSortChange, noDataText }) {
  const filterTypes = React.useMemo(
    () => ({
      fuzzyText: filterRows,
      text: (rows, id, filterValue) => {
        return rows.filter((row) => {
          const rowValue = row.values[id]
          return rowValue !== undefined ? String(rowValue).toLowerCase().startsWith(String(filterValue).toLowerCase()) : true
        })
      },
    }),
    []
  )

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    prepareRow,
    page,
    canPreviousPage,
    canNextPage,
    pageOptions,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    setPageSize,
    state: { pageIndex, pageSize, globalFilter, sortBy },
    visibleColumns,
    preGlobalFilteredRows,
    setGlobalFilter,
    rows,
  } = useTable(
    {
      columns,
      data,
      initialState: {
        pageIndex: currPage,
        pageSize: tableConfig.initialPageSize || 10,
        globalFilter: filterValue,
        sortBy: sortArray,
      },
      filterTypes,
    },
    useFilters,
    useGlobalFilter,
    useSortBy,
    usePagination
  )

  onPageChange = onPageChange.bind(this)
  onFilterChange = onFilterChange.bind(this)
  onSortChange = onSortChange.bind(this)

  React.useEffect(() => {
    onSortChange(sortBy)
  }, [sortBy])

  let paginationArray = [10, 20, 30, 40, 50]
  if (tableConfig.initialPageSize && !paginationArray.includes(tableConfig.initialPageSize)) {
    paginationArray.push(tableConfig.initialPageSize)
    paginationArray.sort(function (a, b) {
      return a - b
    })
  }

  let scrollableClasses = tableConfig.scroll ? ' custom-scrollbar border-bottom' : ''
  let scrollHeightClass = tableConfig.scroll ? { maxHeight: tableConfig.scrollHeight } : {}

  return (
    <div>
      <table id={id + '-header'} className='text-center table table-striped table-sm rt-table' {...getTableProps()}>
        <thead className='rt-head'>
          <tr>
            <th style={{ border: 'none' }} colSpan={visibleColumns.length}>
              <div className='align-items-center d-flex justify-content-between'>
                <div className={tableConfig.showFilter ? '' : ' d-none'}>
                  <GlobalFilter preGlobalFilteredRows={preGlobalFilteredRows} globalFilter={globalFilter} setGlobalFilter={setGlobalFilter} onFilterChange={onFilterChange} />
                </div>
                <div className={tableConfig.showExport ? '' : ' d-none'}>
                  <CSVLink data={data} className='btn btn-block text-center' id={id + '-csv-export-button'} filename={fileName + '.csv'}>
                    {translate('generate_report')}
                  </CSVLink>
                </div>
              </div>
            </th>
          </tr>
          {createHeader(headerGroups)}
        </thead>
      </table>
      <div className={'rt-body' + scrollableClasses} style={scrollHeightClass}>
        <table id={id} className='text-center table table-striped table-sm'>
          <tbody className={tableConfig.scroll ? '' : 'border-bottom'} {...getTableBodyProps()}>
            {createRows(id, page, prepareRow, visibleColumns, noDataText)}
          </tbody>
        </table>
      </div>

      <div id={'pagination-bar'} className={'align-items-center justify-content-between' + (tableConfig.showPagination ? ' d-flex' : ' d-none')}>
        <div className='d-flex'>
          <select
            className='rt-paginate-page-selector'
            value={pageSize}
            onChange={(e) => {
              gotoPage(0)
              onPageChange(0)
              setPageSize(Number(e.target.value))
            }}
          >
            {paginationArray.map((pageSize) => (
              <option key={pageSize} value={pageSize}>
                {pageSize}
              </option>
            ))}
          </select>
          <div>
            {translate('showing')} {1 + pageIndex * pageSize} {translate('to').toLowerCase()} {(pageIndex + 1) * pageSize < rows.length ? (pageIndex + 1) * pageSize : rows.length}{' '}
            {translate('of')}
            {' ' + rows.length} {translate('entries')}
          </div>
        </div>
        <div className='d-flex'>
          <button
            className='page-link rounded-left rt-paginate-button'
            onClick={() => {
              gotoPage(0)
              onPageChange(0)
            }}
            disabled={!canPreviousPage}
          >
            {'First'}
          </button>{' '}
          <button
            className='page-link rt-paginate-button'
            onClick={() => {
              previousPage()
              onPageChange(pageIndex - 1)
            }}
            disabled={!canPreviousPage}
          >
            {'Previous'}
          </button>{' '}
          <button
            className='page-link rt-paginate-button'
            onClick={() => {
              nextPage()
              onPageChange(pageIndex + 1)
            }}
            disabled={!canNextPage}
          >
            {'Next'}
          </button>{' '}
          <button
            className='page-link rounded-right rt-paginate-button'
            onClick={() => {
              gotoPage(pageCount - 1)
              onPageChange(pageCount - 1)
            }}
            disabled={!canNextPage}
          >
            {'Last'}
          </button>{' '}
        </div>
      </div>
    </div>
  )
}

export class GenericTable extends React.Component {
  constructor() {
    super()
    this.state = {}
  }

  render() {
    const { id, tableConfig, columns, data, fileName, page, filter, sort, onPageChange, onFilterChange, onSortChange, noDataText } = this.props

    return (
      <Table
        id={id}
        tableConfig={tableConfig}
        columns={columns}
        data={data}
        fileName={fileName}
        currPage={page}
        filterValue={filter}
        sortArray={sort}
        onPageChange={onPageChange}
        onFilterChange={onFilterChange}
        onSortChange={onSortChange}
        noDataText={noDataText}
      />
    )
  }
}

问题是,那些以字母开头的行和以数字开头的行的表没有正确排序。
以数字开头的行排序在以字母开头的行之后。

export class OperationalHistoryTable extends React.Component {
  constructor() {
    super()
    this.state = {
      table_filter: '',
      table_page: 0,
      table_sort: [
        {
          id: 'event_time',
          desc: true,
        },
      ],
    }
  }

  render() {
    var columns = [
      {
        header: translate('event_time'),
        accessor: 'event_time',
        width: '15%',
        Cell: (row) => {
          return filteredTime(row.cell.value)
        },
      },
      {
        header: translate('event_type'),
        accessor: 'event_type',
        width: '40%',
      },
      {
        header: translate('additional_info'),
        accessor: 'additional_info',
        width: '45%',
      },
    ]

    const tableConfig = {
      showFilter: true,
      showExport: true,
      showPagination: true,
      autoResetPage: false,
    }

    return (
      <GenericTable
        id='operational-history-table'
        tableConfig={tableConfig}
        columns={columns}
        data={this.eventHistoryData()}
        fileName='Operational History'
        page={this.state.table_page}
        filter={this.state.table_filter}
        sort={this.state.table_sort}
        onPageChange={(pageValue) => {
          this.setState({ table_page: pageValue })
        }}
        onFilterChange={(filter) => {
          this.setState({
            table_filter: filter,
            table_page: 0,
          })
        }}
        onSortChange={(sortBy) => {
          this.setState({ table_sort: sortBy })
        }}
        noDataText={translate('no_events')}
      />
    )
  }

我附上一张描述这个问题的图片。当我点击按升序列排序行时,以数字开头的行被放置在最后。
但是,只有字母的行将被正确排序,即,例如,以字母“a”开头的行位于以字母“b”开头的行之前。

tkqqtvp1

tkqqtvp11#

默认情况下,useSortBy钩子先对文本值排序,然后对数字排序。要实现预期的先对数字排序的行为,您需要覆盖默认的排序规则。
您需要使用自己的规则覆盖sortTypebasic值。

sortType参数

sortType:String|函数(行A:,rowB:,columnId:字符串,描述:布尔)
sortType需要三个参数:要比较的两行和要考虑的列的标识符。

示例

声明自定义排序函数

const {
  // ...
} = useTable(
  {
    columns,
    data,
    initialState: {
      // ...
    },
    filterTypes,

    // Here --------
    sortTypes: {
      custom: (rowA, rowB, columnId) => {
        const a = rowA.values[columnId];
        const b = rowB.values[columnId];
        
        if (!isNaN(Number(a)) && !isNaN(Number(b))) {
          return Number(a) - Number(b);
        }
        return a.localeCompare(b);
      }
    },
    // -------------

  },
  useFilters,
  useGlobalFilter,
  useSortBy,
  usePagination
)

对列使用排序函数

columns: [
  {
    Header: "Column #1",
    accessor: "column_1",
    sortType: "custom" // here
  },
  {
    Header: "Column #2",
    accessor: "column_2",
    sortType: "custom" // here
  }
]

相关问题