Why Is Ant Design’s Table So Slow? Exploring Memoization, Virtualization, and Cell Updates
This article examines why Ant Design’s Table component often feels sluggish, covering historical design choices, memoization pitfalls with external state, the challenges of virtual scrolling for editable tables, and how the shouldCellUpdate and onCell APIs provide finer‑grained rendering control.
Every few months a new Table component library appears, yet Ant Design’s Table is repeatedly criticized for being "slow". The reasons stem from historical design decisions and unavoidable trade‑offs.
In the early v4 rewrite, Ant Design introduced an alpha Table that heavily memoizes rows and columns using useMemo. As long as the data prop does not change, the Table will not re‑render, which matches most expectations. However, when a column’s render function depends on external state, the Table still re‑renders even though data is unchanged.
const [count, setCount] = React.useState(0);
const columns = [{
render: () => count,
}];
return <Table columns={columns} {...otherProps} />;Because the render closure captures count, changes to count force a re‑render. This pattern is common when developers want a cell to be editable or interactive.
Developers might try to add a deps array to control when the Table should update, but in complex codebases it is easy to forget to include new dependencies, leading to stale UI and hard‑to‑track bugs.
To give developers more granular control, Ant Design provides a more atomic shouldCellUpdate method, which focuses on cell‑level memoization rather than relying on the whole deps list.
Another frequent complaint is the lack of built‑in virtual scrolling. Virtual scrolling renders only visible rows to improve performance, but for editable tables this creates problems: rows that are not rendered have no form fields, so when the form is submitted only the visible rows are collected. Although Ant Design’s Form can force collection of unmounted fields via getFieldsValue(true), this may also retrieve unwanted data.
Additional virtual‑scroll issues include unknown widths for long cells, loss of automatic column width adaptation, and accessibility concerns for cells that span multiple rows.
Breaking changes also affect developers. For example, the misspelled feildNames API was corrected to fieldNames, but the old name remained for compatibility throughout the major version.
Table’s render method can return a node with props (e.g., rowSpan, colSpan), but Ant Design now recommends using onCell, which returns only props. The render approach forces child rendering and potential side effects, whereas onCell avoids unnecessary renders and enables better optimization.
const columns = [{
render: () => ({
children: 'Hello World',
rowSpan: 2,
colSpan: 2,
})
}]; const columns = [{
render: () => 'Hello World',
onCell: () => ({
rowSpan: 2,
colSpan: 2,
})
}];In the latest version, examples have been switched to use onCell, and developers are warned that returning props from render will be deprecated in the next major release.
Overall, optimizing a Table involves balancing performance with maintainability. While fine‑tuned memoization can solve specific issues, broader business requirements often introduce new edge cases, making a one‑size‑fits‑all "silver bullet" impossible.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alipay Experience Technology
Exploring ultimate user experience and best engineering practices
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
