React-Table:数据变化时行排序、过滤重置

9
我正在尝试在react-table中对数据进行排序,但是随着新数据的到来,排序被取消。包含表格的组件从prop中获取其数据。该数据本身来自redux,每15秒更新一次,以获取来自服务器的最新数据(其中数据经常更改)。
我想要的是对数据进行排序,并使这些排序保持不变,即使数据发生更改时也是如此。实际发生的是,我按列标题对表格进行排序,然后当数据发生更改时,排序被删除。
我已经尝试过:
- 将autoResetSortBy设置为false - 实施了这个:https://react-table.tanstack.com/docs/faq#how-do-i-stop-my-table-state-from-automatically-resetting-when-my-data-changes - 通过阅读文档和示例寻找明显的区别
排序有效: enter image description here

但是一旦数据发生变化,它就会变成这样: enter image description here

我希望保留排序过滤器,以便在新数据到达时(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
1个回答

2
不要在其他React组件内声明React组件。每次一个React函数组件重新渲染时,它会重新创建函数体中声明的所有内容,同时保留来自各种hooks(例如useState、useCallback、useMemo等)的记忆变量的引用。
在另一个组件的主体内声明组件时,在每次渲染时都会获得一个新的组件,该组件将不会保留先前渲染中所具有的任何内部状态。因此,您的UI选择被删除。
在单独的文件中声明Table,并将其导入到TableTest中。或者,将Table中的所有内容移动到TableTest的主体内。
此外,我还会摆脱你的两个useMemo hooks,因为它们没有实现任何目标。在第一种情况下,如果您有一个静态数组/对象,请在组件范围之外声明它,而在第二种情况下,localData已经由状态钩子有效地进行了记忆化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接