react-table 行排序过滤器在数据更改时重置
react-table rows sort filter resetting on data change
我正在尝试对 react-table 中的数据进行排序,但是当新数据到达时,排序无效。
包含 table 的组件从 prop 获取数据。该数据本身来自 redux,它每 15 秒更新一次来自服务器的最新数据(它经常更改)。
我想要对数据进行排序,为了让这些排序保持原样 as/when 数据会发生变化。
实际发生的是我按列 header 对 table 进行排序,然后当数据更改时,排序被删除。
我试过:
- 将
autoResetSortBy
设置为 false
- 实现了这个:https://react-table.tanstack.com/docs/faq#how-do-i-stop-my-table-state-from-automatically-resetting-when-my-data-changes
- 通读文档和示例以寻找明显的差异
排序作品:
但是一旦数据改变就变成这样:
我想保留排序过滤器,以便在新数据到达时(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 功能组件重新渲染时,它都会重新创建在其函数体中声明的所有内容,同时保留对来自各种钩子 useState
、useCallback
、useMemo
e.t.c.[ 的记忆变量的引用。 =19=]
当您在另一个组件的主体中声明一个组件时,您将在每个渲染器上获得一个 新 组件,它将不会保留它在上一个渲染器中的任何内部状态。因此,您的 UI 选择已被删除。
在单独的文件中声明 Table
并将其导入 TableTest
。或者,只需将 Table
内的所有内容移动到 TableTest
.
的正文中
我也会摆脱你的两个 useMemo
钩子,因为它们没有取得任何成就。在第一种情况下,如果你有一个静态 array/object 只需在组件范围之外声明它,而在第二种情况下,localData
已经被状态挂钩有效地记忆了。
我正在尝试对 react-table 中的数据进行排序,但是当新数据到达时,排序无效。 包含 table 的组件从 prop 获取数据。该数据本身来自 redux,它每 15 秒更新一次来自服务器的最新数据(它经常更改)。
我想要对数据进行排序,为了让这些排序保持原样 as/when 数据会发生变化。 实际发生的是我按列 header 对 table 进行排序,然后当数据更改时,排序被删除。
我试过:
- 将
autoResetSortBy
设置为 false - 实现了这个:https://react-table.tanstack.com/docs/faq#how-do-i-stop-my-table-state-from-automatically-resetting-when-my-data-changes
- 通读文档和示例以寻找明显的差异
排序作品:
但是一旦数据改变就变成这样:
我想保留排序过滤器,以便在新数据到达时(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 功能组件重新渲染时,它都会重新创建在其函数体中声明的所有内容,同时保留对来自各种钩子 useState
、useCallback
、useMemo
e.t.c.[ 的记忆变量的引用。 =19=]
当您在另一个组件的主体中声明一个组件时,您将在每个渲染器上获得一个 新 组件,它将不会保留它在上一个渲染器中的任何内部状态。因此,您的 UI 选择已被删除。
在单独的文件中声明 Table
并将其导入 TableTest
。或者,只需将 Table
内的所有内容移动到 TableTest
.
我也会摆脱你的两个 useMemo
钩子,因为它们没有取得任何成就。在第一种情况下,如果你有一个静态 array/object 只需在组件范围之外声明它,而在第二种情况下,localData
已经被状态挂钩有效地记忆了。