Repository navigation
[Svelte] Client-side paginatedRowModel doesn't recompute when pagination state is externally controlled via state.pagination + onPaginationChange #6374
Description
TanStack Table version
v9.0.0-beta.29
Framework/Library version
@sveltejs/kit 2.69.1
Describe the bug and the steps to reproduce it
Describe the bug
When pagination state is externally controlled (v8-style state.pagination + onPaginationChange, or the new createTableState helper), table.getState().pagination.pageIndex updates correctly, but table.getRowModel().rows never reflects the new page — it always shows the rows from pageIndex: 0.
The identical pattern works correctly for sorting (state.sorting + onSortingChange), so this appears isolated to paginatedRowModel specifically.
Using manualPagination: true (server-side pagination, no client-side paginatedRowModel slicing) works correctly — the bug only affects client-side pagination.
Your minimal, reproducible example
<script lang="ts">
import {
createTable,
createTableState,
tableFeatures,
rowPaginationFeature,
createPaginatedRowModel,
type PaginationState,
} from '@tanstack/svelte-table'
const features = tableFeatures({
rowPaginationFeature,
paginatedRowModel: createPaginatedRowModel(),
})
const [pagination, setPagination] = createTableState<PaginationState>({
pageIndex: 0,
pageSize: 15,
})
let list = $state(/* e.g. 250 rows */)
const table = createTable({
features,
columns,
get data() {
return list
},
state: {
get pagination() {
return pagination()
},
},
onPaginationChange: (updater) => {
setPagination(updater) // <-- presence of this alone breaks getRowModel()
},
})
</script>
<!-- table.nextPage() correctly updates table.getState().pagination.pageIndex to 1,
but table.getRowModel().rows still shows the same 15 rows as page 0 -->
<button onclick={() => table.nextPage()}>Next</button>Steps to reproduce
- Create a table with
rowPaginationFeature+createPaginatedRowModel(), more data than fits on one page (e.g. 250 rows,pageSize: 15). - Control pagination externally via
state.pagination+onPaginationChange(tested both with a raw Svelte$stateobject and withcreateTableState). - Click "next page" (
table.nextPage()ortable.setPageIndex(n)). - Observe
table.getState().pagination.pageIndex— it updates correctly. - Observe
table.getRowModel().rows— it does not change; the same rows from page 0 keep being returned.
Expected behavior
table.getRowModel().rows should reflect the current pageIndex/pageSize, the same way it does when the table manages pagination internally (no state.pagination/onPaginationChange provided) or the same way sortedRowModel reacts to externally-controlled sorting.
How often does this bug happen?
Every time, 100% reproducible.
Platform
- Version of TanStack Table:
9.0.0-beta.29 - Framework: Svelte 5 (Runes mode)
Additional context
- Confirmed this is not a
$state/proxy-identity issue on the app side: tested both a rawlet pagination = $state({...})andcreateTableState<PaginationState>(...), identical behavior in both cases. - The identical pattern (
state.sorting+onSortingChange) works correctly, so this seems isolated to the pagination row model's memoization/dependency tracking specifically. - The equivalent v8 configuration (
state.pagination+onPaginationChange,getPaginationRowModel: getPaginationRowModel()) works correctly — this is a regression relative to v8 behavior. - Workaround currently in use: let the table manage pagination state fully internally (no
state.pagination/onPaginationChange), and observe page changes passively via an effect ontable.getState().pagination.pageIndexto drive side effects (e.g. resetting a selected-row index).
Your Minimal, Reproducible Example - (Sandbox Highly Recommended)
Screenshots or Videos (Optional)
No response
Do you intend to try to help solve this bug with your own PR?
None
Terms & Code of Conduct
- I agree to follow this project's Code of Conduct
- I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.
Activity
frenandre commentedon Jul 3, 2026
Update: I've narrowed this down further and it turns out this is not a library bug — it was a reactivity mismatch in my own code between the Svelte primitive used for the
datasource and themanualPaginationmode. Apologies for the noise.Root cause: the reactivity primitive backing the
datagetter needs to matchmanualPagination:manualPagination: false(client-side pagination) →datasource must be$state:let list = $state(data.list.content) const table = createTable({ columns, get data() { return list }, manualPagination: false, // ... })manualPagination: true(server-side pagination) →datasource must be$derived:let list = $derived(data.list.content) const table = createTable({ columns, get data() { return list }, manualPagination: true, // ... })With the correct combination,
state.pagination+onPaginationChange(externally controlled, no workaround needed) works correctly in both modes —table.getRowModel().rowsupdates as expected on page change.The mismatched combination (
$state+manualPagination: true, or$derived+manualPagination: false) is what caused the symptom I originally reported (pageIndexupdates,getRowModel().rowsdoesn't).I'd still guess there's something worth looking at here — ideally either primitive should work regardless of
manualPagination, so if there's a reason the adapter's dependency tracking distinguishes between$stateand$derivedsources depending on the mode, it might be worth a note in the docs (I didn't see this documented anywhere) or a fix so both are supported uniformly. But this is no longer the sharp reproducible library bug I described — closing this out / leaving it to maintainer discretion whether to keep open as a docs/DX issue or close.Thanks for the library either way, and sorry again for the initial misdiagnosis!
frenandre commentedon Jul 5, 2026
Final update: found the actual root cause — this was autoResetPageIndex (defaults to true when manualPagination is false) resetting pageIndex back to 0 immediately after each page change. Setting autoResetPageIndex: false resolved it completely. Not a library bug — closing this out, sorry for the back-and-forth!