Skip to content

Commit 287ef4c

Browse files
fix(table): keep rows rendered when pageSizes prop changes at runtime
Pagination's mount effect persists the initial page size into Table's internal pagination state. If a consumer later passes a different pagination.pageSizes (e.g. derived from the viewport height), the stale internal pageSize no longer matches any entry: the pageData memo's lookup loop falls through to return null and the table renders its empty state ("No data found") with data still present, recovering only on remount. Two-layer fix: - usePagination: normalize a merged pageSize that is not contained in the merged pageSizes to pageSizes[0], keeping the data slice, pager count, and currentPage clamp consistent. - Table pageData memo: replace the terminal return-null fallthrough with a defensive slice using the first available size. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent f22fb38 commit 287ef4c

3 files changed

Lines changed: 39 additions & 0 deletions

File tree

src/components/Table/Hooks/usePagination.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,15 @@ export default function usePagination(
8080
}
8181
);
8282

83+
// A changed pageSizes prop can orphan the pageSize persisted by Pagination's mount effect
84+
if (
85+
mergedPagination.pageSizes &&
86+
mergedPagination.pageSize !== undefined &&
87+
!mergedPagination.pageSizes.includes(mergedPagination.pageSize)
88+
) {
89+
mergedPagination.pageSize = mergedPagination.pageSizes[0];
90+
}
91+
8392
// Reset `current` if data length or pageSize changed
8493
const pages: number[] = mergedPagination.pageSizes!;
8594
let maxPage: number;

src/components/Table/Table.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,14 @@ function InternalTable<RecordType extends object = any>(
579579
);
580580
}
581581
}
582+
583+
// pageSize not in pageSizes: fall back to the first size instead of rendering empty
584+
const fallbackPageSize: number = pageSizes[0] ?? DEFAULT_PAGE_SIZE;
585+
mergedPagination.pageSize = fallbackPageSize;
586+
return mergedData.slice(
587+
(currentPage - 1) * fallbackPageSize,
588+
currentPage * fallbackPageSize
589+
);
582590
} else {
583591
if (mergedData.length < total!) {
584592
if (mergedData.length > pageSize) {

src/components/Table/Tests/Table.pagination.test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from 'react';
2+
import { act } from 'react-dom/test-utils';
23
import Enzyme, { mount } from 'enzyme';
34
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
45
import Table from '../index';
@@ -77,6 +78,27 @@ describe('Table.table-pagination', () => {
7778
expect(renderedNames(wrapper)).toEqual(['Lola']);
7879
});
7980

81+
it('keeps rendering rows when a dynamic pageSizes prop changes value', () => {
82+
// act() flushes Pagination's mount effect, which persists the initial size (the bug trigger)
83+
let wrapper;
84+
act(() => {
85+
wrapper = mount(
86+
createTable({
87+
dataSource: longData,
88+
pagination: { pageSizes: [10] },
89+
})
90+
);
91+
});
92+
wrapper.update();
93+
expect(renderedNames(wrapper)).toHaveLength(10);
94+
95+
act(() => {
96+
wrapper.setProps({ pagination: { pageSizes: [9] } });
97+
});
98+
wrapper.update();
99+
expect(renderedNames(wrapper)).toHaveLength(9);
100+
});
101+
80102
it('should not crash when trigger onChange in render', () => {
81103
function App() {
82104
const [page, setPage] = React.useState({

0 commit comments

Comments
 (0)