Skip to content

Commit

Permalink
fix: wires up abort controller logic for list columns (#9180)
Browse files Browse the repository at this point in the history
### What?
List column state could become out of sync if toggling columns happened
in rapid succession as seen in CI. Or when using a spotty connection
where responses could come back out of order.

### Why?
State was not being preserved between toggles. Leading to incorrect
columns being toggled on/off.

### How?
Updates internal column state before making the request to the server so
when a future toggle occurs it has up to date state of all columns. Also
introduces an abort controller to prevent the out of order response
issue.
  • Loading branch information
JarrodMFlesch authored Nov 13, 2024
1 parent cea7d58 commit 129fadf
Showing 1 changed file with 61 additions and 12 deletions.
73 changes: 61 additions & 12 deletions packages/ui/src/elements/TableColumns/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { Column } from '../Table/index.js'
import { useConfig } from '../../providers/Config/index.js'
import { usePreferences } from '../../providers/Preferences/index.js'
import { useServerFunctions } from '../../providers/ServerFunctions/index.js'
import { abortAndIgnore } from '../../utilities/abortAndIgnore.js'

export interface ITableColumns {
columns: Column[]
Expand Down Expand Up @@ -77,25 +78,36 @@ export const TableColumnsProvider: React.FC<Props> = ({
const { getPreference, setPreference } = usePreferences()

const [tableColumns, setTableColumns] = React.useState(columnState)
const tableStateControllerRef = React.useRef<AbortController>(null)

const moveColumn = useCallback(
async (args: { fromIndex: number; toIndex: number }) => {
abortAndIgnore(tableStateControllerRef.current)

const { fromIndex, toIndex } = args
const withMovedColumn = [...tableColumns]
const [columnToMove] = withMovedColumn.splice(fromIndex, 1)
withMovedColumn.splice(toIndex, 0, columnToMove)

const { state: columnState, Table } = await getTableState({
setTableColumns(withMovedColumn)

const controller = new AbortController()
tableStateControllerRef.current = controller

const result = await getTableState({
collectionSlug,
columns: sanitizeColumns(withMovedColumn),
docs,
enableRowSelections,
renderRowTypes,
signal: controller.signal,
tableAppearance,
})

setTableColumns(columnState)
setTable(Table)
if (result) {
setTableColumns(result.state)
setTable(result.Table)
}
},
[
tableColumns,
Expand All @@ -111,24 +123,55 @@ export const TableColumnsProvider: React.FC<Props> = ({

const toggleColumn = useCallback(
async (column: string) => {
const toggledColumns: Pick<Column, 'accessor' | 'active'>[] = tableColumns.map((col) => {
return {
accessor: col.accessor,
active: col.accessor === column ? !col.active : col.active,
}
})
abortAndIgnore(tableStateControllerRef.current)

const { newColumnState, toggledColumns } = tableColumns.reduce<{
newColumnState: Column[]
toggledColumns: Pick<Column, 'accessor' | 'active'>[]
}>(
(acc, col) => {
if (col.accessor === column) {
acc.newColumnState.push({
...col,
accessor: col.accessor,
active: !col.active,
})
acc.toggledColumns.push({
accessor: col.accessor,
active: !col.active,
})
} else {
acc.newColumnState.push(col)
acc.toggledColumns.push({
accessor: col.accessor,
active: col.active,
})
}

const { state: columnState, Table } = await getTableState({
return acc
},
{ newColumnState: [], toggledColumns: [] },
)

setTableColumns(newColumnState)

const controller = new AbortController()
tableStateControllerRef.current = controller

const result = await getTableState({
collectionSlug,
columns: toggledColumns,
docs,
enableRowSelections,
renderRowTypes,
signal: controller.signal,
tableAppearance,
})

setTableColumns(columnState)
setTable(Table)
if (result) {
setTableColumns(result.state)
setTable(result.Table)
}
},
[
tableColumns,
Expand Down Expand Up @@ -233,6 +276,12 @@ export const TableColumnsProvider: React.FC<Props> = ({
sortColumnProps,
])

React.useEffect(() => {
return () => {
abortAndIgnore(tableStateControllerRef.current)
}
}, [])

return (
<TableColumnContext.Provider
value={{
Expand Down

0 comments on commit 129fadf

Please sign in to comment.