diff --git a/web/packages/design/src/DataTable/useTable.ts b/web/packages/design/src/DataTable/useTable.ts index e8c70f3bd2dd0..16d69ee54f113 100644 --- a/web/packages/design/src/DataTable/useTable.ts +++ b/web/packages/design/src/DataTable/useTable.ts @@ -42,46 +42,71 @@ export default function useTable({ disableFilter = false, ...props }: TableProps) { - const [state, setState] = useState<{ - data: T[]; - searchValue: string; - sort?: Sort; - pagination?: Pagination; - }>(() => { + // Determine the initial sort + let initialSort: Sort | undefined; + if (!customSort) { + const { initialSort: initialSortProp } = props; // Finds the first sortable column to use for the initial sorting let col: TableColumn | undefined; - if (!customSort) { - const { initialSort } = props; - if (initialSort) { - col = initialSort.altSortKey - ? columns.find(col => col.altSortKey === initialSort.altSortKey) - : columns.find(col => col.key === initialSort.key); - } else { - col = columns.find(column => column.isSortable); - } + if (initialSortProp) { + col = initialSortProp.altSortKey + ? columns.find(col => col.altSortKey === initialSortProp.altSortKey) + : columns.find(col => col.key === initialSortProp.key); + } else { + col = columns.find(column => column.isSortable); } + if (col) { + initialSort = { + key: (col.altSortKey || col.key) as keyof T, + onSort: col.onSort, + dir: initialSortProp?.dir || 'ASC', + }; + } + } - return { - data: [], - searchValue: clientSearch?.initialSearchValue || '', - sort: col - ? { - key: (col.altSortKey || col.key) as keyof T, - onSort: col.onSort, - dir: props.initialSort?.dir || 'ASC', - } - : undefined, - pagination: pagination - ? { - paginatedData: paginateData([], pagination.pageSize), - currentPage: 0, - pagerPosition: pagination.pagerPosition, - pageSize: pagination.pageSize || 15, - CustomTable: pagination.CustomTable, - } - : undefined, + // Compute the initial data + const initialSearchValue = clientSearch?.initialSearchValue || ''; + let initialData: T[]; + if (serversideProps || disableFilter || !data?.length) { + initialData = data || []; + } else { + initialData = sortAndFilter( + data, + initialSearchValue, + initialSort, + searchableProps || + (columns + .filter(column => column.key) + .map(column => column.key) as (keyof T & string)[]), + searchAndFilterCb, + showFirst + ); + } + + // Compute initial pagination if applicable + let initialPagination: Pagination | undefined; + if (pagination) { + const pages = paginateData(initialData, pagination.pageSize); + initialPagination = { + paginatedData: pages, + currentPage: 0, + pagerPosition: pagination.pagerPosition, + pageSize: pagination.pageSize || 15, + CustomTable: pagination.CustomTable, }; - }); + } + + const [state, setState] = useState<{ + data: T[]; + searchValue: string; + sort?: Sort; + pagination?: Pagination; + }>(() => ({ + data: initialData, + searchValue: initialSearchValue, + sort: initialSort, + pagination: initialPagination, + })); function searchAndFilterCb( targetValue: any, diff --git a/web/packages/teleport/src/JoinTokens/JoinTokens.test.tsx b/web/packages/teleport/src/JoinTokens/JoinTokens.test.tsx index 8b0962faabd7d..3a93bc72f8b17 100644 --- a/web/packages/teleport/src/JoinTokens/JoinTokens.test.tsx +++ b/web/packages/teleport/src/JoinTokens/JoinTokens.test.tsx @@ -41,6 +41,12 @@ describe('JoinTokens', () => { render(); const optionButtons = await screen.findAllByText(/options/i); await userEvent.click(optionButtons[0]); + // TODO(kiosion): What's happening here is that DataTable re-renders faster than `userEvent.click` can be fired, so the button ref is stale. + // This wasn't an issue prior since DataTable used to init with no data regardless of what was passed in, + // so 'findAllByText' would wait a few ms before finding the text on commit 2. + // Querying and clicking a second time works but there's definitely a better way to handle this. + const _optionButtons = screen.getAllByText(/options/i); + await userEvent.click(_optionButtons[0]); const editButtons = await screen.findAllByText(/view\/edit/i); await userEvent.click(editButtons[0]); expect(screen.getByText(/edit token/i)).toBeInTheDocument();