react-table 行排序过滤器在数据更改时重置

react-table rows sort filter resetting on data change

我正在尝试对 react-table 中的数据进行排序,但是当新数据到达时,排序无效。 包含 table 的组件从 prop 获取数据。该数据本身来自 redux,它每 15 秒更新一次来自服务器的最新数据(它经常更改)。

我想要对数据进行排序,为了让这些排序保持原样 as/when 数据会发生变化。 实际发生的是我按列 header 对 table 进行排序,然后当数据更改时,排序被删除。

我试过:

排序作品:

但是一旦数据改变就变成这样:

我想保留排序过滤器,以便在新数据到达时(99% 的时间相同,但 1% 的时间列值不同或有新行)按以下方式排序应用的排序过滤器。

这是我的代码的一个简化示例(尽可能小):

import * as React from 'react'
import { useTable, Column, useSortBy } from 'react-table'
import * as SharedTypes from '@shared/declarations'

interface Props {
    serverData: SharedTypes.API.MarketBotSummary[]
}

export const TableTest: React.StatelessComponent<Props> = ({ serverData }: Props) => {

    const [localData, setLocalData] = React.useState<SharedTypes.API.MarketBotSummary[]>(serverData)
    const skipPageResetRef = React.useRef<boolean>(false)

    React.useEffect(() => {
        skipPageResetRef.current = true
        setLocalData(serverData)
        console.log('data changed', serverData)
    }, [serverData])

    React.useEffect(() => {
        // After the table has updated, always remove the flag   
        skipPageResetRef.current = false     
    })


    const Table = ({ columns, data }: { columns: Column<SharedTypes.API.MarketBotSummary>[], data: SharedTypes.API.MarketBotSummary[]}) => {
        // Use the state and functions returned from useTable to build your UI
        const {
          getTableProps,
          getTableBodyProps,
          headerGroups,
          rows,
          prepareRow,
          // @ts-ignore
          state: { sortBy }
        } = useTable(
            {
                columns,
                data,
                // @ts-ignore
                // autoResetSortBy: false,
                // autoResetFilters: false,
                autoResetPage: !skipPageResetRef.current,
                autoResetExpanded: !skipPageResetRef.current,
                autoResetGroupBy: !skipPageResetRef.current,
                autoResetSelectedRows: !skipPageResetRef.current,
                autoResetSortBy: !skipPageResetRef.current,
                autoResetFilters: !skipPageResetRef.current,
                autoResetRowState: !skipPageResetRef.current,
            },
            useSortBy
        )

        // Render the UI for your table
        return (
            <>
                <table {...getTableProps()} className="ui celled very compact structured table">
                    <thead>
                    {
                        // @ts-ignore
                        headerGroups.map(headerGroup => (
                        <tr {...headerGroup.getHeaderGroupProps()}>
                        {
                            // @ts-ignore
                            headerGroup.headers.map(column => (
                            <th {
                                    // @ts-ignore
                                    ...column.getHeaderProps(column.getSortByToggleProps())
                                }>
                                {column.render('Header')}
                                <span>
                                    {
                                        // @ts-ignore
                                        column.isSorted ? column.isSortedDesc ? ' ' : ' ' : ''
                                    }
                                </span>
                            </th>
                        ))}
                        </tr>
                    ))}
                    </thead>
                    <tbody {...getTableBodyProps()}>
                    {
                        // @ts-ignore
                        rows.map((row) => {
                            prepareRow(row)
                            
                            return (
                                <tr {...row.getRowProps()}>
                                    {row.cells.map(
                                        // @ts-ignore
                                        cell => <td {...cell.getCellProps({ className: cell.column?.className?.(cell.value, row.original) })}>
                                            {cell.render('Cell')}
                                        </td>
                                        )}
                                </tr>
                            )
                        })}
                    </tbody>
                </table>
                <pre>
                    <code>
                        {JSON.stringify(
                            {
                                sortBy,
                            },
                            null,
                            2
                        )}
                    </code>
                </pre>
            </>
        )
    }
    
    
    const columns = React.useMemo(
        () => [
          {
            Header: 'Data',
            columns: [
                {
                  Header: 'Quote',
                  accessor: 'quote',
                },
                {
                    Header: 'Symbol',
                    accessor: 'symbol',
                },
                {
                    Header: 'Mode',
                    accessor: 'status',                 
                },
                {
                    Header: 'direction',
                    accessor: 'tradeDirection',
                },
            ],
          },
        ],
        []
    )

    const data = React.useMemo(
        () => localData,
        [localData]
    )


    return (
        <Table columns={columns} data={data} />
    )
}

export default TableTest

不要在其他 React 组件中声明 React 组件。每次 React 功能组件重新渲染时,它都会重新创建在其函数体中声明的所有内容,同时保留对来自各种钩子 useStateuseCallbackuseMemo e.t.c.[ 的记忆变量的引用。 =19=]

当您在另一个组件的主体中声明一个组件时,您将在每个渲染器上获得一个 组件,它将不会保留它在上一个渲染器中的任何内部状态。因此,您的 UI 选择已被删除。

在单独的文件中声明 Table 并将其导入 TableTest。或者,只需将 Table 内的所有内容移动到 TableTest.

的正文中

我也会摆脱你的两个 useMemo 钩子,因为它们没有取得任何成就。在第一种情况下,如果你有一个静态 array/object 只需在组件范围之外声明它,而在第二种情况下,localData 已经被状态挂钩有效地记忆了。