Summary
A Vite production build can freeze the Chrome renderer when a trusted pointer click synchronously updates React state, passes a fresh one-row data array into TanStack Table, reads table.getRowModel().rows.length, and mounts a child that suspends on a timer.
The repro is standalone and uses only local state/data. It does not depend on TanStack Router, TanStack Query, React Compiler, Vite React plugin, APIs, auth, or any production app code.
Reproduction
Standalone repro:
https://github.com/HaukeSchnau/trusted-click-table-suspense-freeze-repro
git clone https://github.com/HaukeSchnau/trusted-click-table-suspense-freeze-repro.git
cd trusted-click-table-suspense-freeze-repro
pnpm install
pnpm check
pnpm preview:repro
Then open http://127.0.0.1:4174/ in Chrome and click Synchronous active row.
Expected behavior
The click completes and the page remains responsive. The Suspense boundary should handle the thrown timer promise and resume rendering normally.
Actual behavior
The Chrome tab freezes during the click. Reloading or closing the tab is required to recover.
Environment
- React
19.2.3
@tanstack/react-table 8.21.3
- Vite
7.3.0
- Chrome
- macOS
Reduced trigger
const columns: [] = [];
const coreRowModel = getCoreRowModel();
let resolved = false;
let promise: Promise<void> | undefined;
function Suspender() {
if (!resolved) {
promise ??= new Promise((resolve) => {
window.setTimeout(() => {
resolved = true;
resolve();
});
});
throw promise;
}
return null;
}
function App() {
const [active, setActive] = useState(false);
const table = useReactTable({
data: active ? [null] : [],
columns,
getCoreRowModel: coreRowModel,
});
return (
<>
{table.getRowModel().rows.length ? (
<Suspense fallback={null}>
<Suspender />
</Suspense>
) : null}
<button id="sync-active" onClick={() => setActive(true)}>
Synchronous active row
</button>
</>
);
}
Notes
The smallest trigger I’ve found is:
trusted click -> synchronous React state update -> fresh TanStack Table data -> table.getRowModel() read -> React Suspense child suspends on a timer -> Chrome renderer freeze.
This might ultimately be an interaction with React Suspense, but the repro becomes responsive when the TanStack Table row-model read is removed, so I’m filing here first.
Summary
A Vite production build can freeze the Chrome renderer when a trusted pointer click synchronously updates React state, passes a fresh one-row
dataarray into TanStack Table, readstable.getRowModel().rows.length, and mounts a child that suspends on a timer.The repro is standalone and uses only local state/data. It does not depend on TanStack Router, TanStack Query, React Compiler, Vite React plugin, APIs, auth, or any production app code.
Reproduction
Standalone repro:
https://github.com/HaukeSchnau/trusted-click-table-suspense-freeze-repro
git clone https://github.com/HaukeSchnau/trusted-click-table-suspense-freeze-repro.git cd trusted-click-table-suspense-freeze-repro pnpm install pnpm check pnpm preview:reproThen open
http://127.0.0.1:4174/in Chrome and clickSynchronous active row.Expected behavior
The click completes and the page remains responsive. The Suspense boundary should handle the thrown timer promise and resume rendering normally.
Actual behavior
The Chrome tab freezes during the click. Reloading or closing the tab is required to recover.
Environment
19.2.3@tanstack/react-table8.21.37.3.0Reduced trigger
Notes
The smallest trigger I’ve found is:
trusted click -> synchronous React state update -> fresh TanStack Table data ->
table.getRowModel()read -> React Suspense child suspends on a timer -> Chrome renderer freeze.This might ultimately be an interaction with React Suspense, but the repro becomes responsive when the TanStack Table row-model read is removed, so I’m filing here first.