@rc-component/table: Low-Level React Table Primitives
📋 Low-level table primitives for React, maintained in the Ant Design ecosystem.
At a glance
- What is it?
- @rc-component/table gives React developers a TypeScript-first table layer for column layouts, fixed headers, expandable rows, sticky behavior, and virtual rendering. It suits design-system authors who need table primitives rather than a complete visual component, with the trade-off that consumers own styling and composition decisions.
- Who is it for?
- Adopt @rc-component/table when a product or design system needs controllable React table mechanics beneath its own presentation layer. Do not choose it for a quick styled table unless its low-level API, prefix classes, and styling expectations fit the project.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 39 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why react-component/table Exists Below Ant Design Table
@rc-component/table addresses developers who need the mechanics of a React data table without adopting a finished visual design. Its API accepts a record array, column definitions, row identity rules, expansion state, scroll dimensions, sticky offsets, summaries, and element overrides. That makes it relevant to component libraries, internal design systems, and applications whose tables need behavior that differs from a conventional row-and-header component.
The repository describes the package as part of the Ant Design ecosystem and states that it is used by Ant Design Table and other React data display experiences. This positioning matters when choosing it. A low-level primitive gives the caller control over class names, rendered elements, expansion rendering, and component substitution, but it does not promise a complete product interface. The README shows data and columns being passed to Table, while package.json identifies published CSS under `assets/*.css` alongside CommonJS, ES module, and TypeScript entry points.
This is a different adoption decision from choosing Ant Design Table as the user-facing component. The primitives therefore sit below that layer and are most useful when an application or another component package needs to assemble its own table API. An application looking for an immediately styled table may find the lower-level choice unnecessary, while a library author may find a high-level table dependency too constraining.
Column, Record, and Row Identity Flow
The basic data path is explicit. A caller defines a record interface, places those records in an array, maps fields to column definitions, and passes both arrays to the component. Each column can supply a `dataIndex`, `key`, `title`, and optional `width`. The sample gives `Name` and `Age` explicit widths, while `Address` has no width. This gives the library enough information to associate configured columns with record fields without requiring a generic page component.
Row identity is controlled by `rowKey`. Its default is the string `key`, meaning the component reads the field named `key`. It can instead be a function receiving the record and index. Stable identity becomes especially important when records are edited, sorted, or replaced, and when rows can expand. The documented API also allows callbacks for row props and classes through `onRow` and `rowClassName`, leaving presentation behavior outside the basic rendering path.
The package is TypeScript-first, and the README imports both the component and `ColumnsType`. In the example, `ColumnsType<User>` binds column configuration to the `User` record shape. This is a meaningful benefit for reusable tables because consumers can define their data contract once and pass it into the column array. It does not, however, describe runtime validation of arbitrary record data, so TypeScript typing should not be treated as a substitute for valid application data.
Scroll, Fixed Headers, and Sticky Positioning
The `scroll` property controls horizontal and vertical table dimensions. Its documented values include `x` and `y`, each of which can be a number indicating body width or height. This is a direct configuration path for tables that cannot show all columns or rows in the available viewport. It also affects layout decisions elsewhere in the API: `useFixedHeader` creates a separate header table, and the README advises setting widths for columns when using that mode.
Sticky positioning is separate from ordinary scrolling. The `sticky` property can be a boolean or an object containing `offsetHeader`, `offsetScroll`, and `getContainer`. The object form gives the caller a way to account for an existing header and configure the element against which sticky behavior is calculated. That is useful in application shells where the table starts below navigation, but it also moves layout verification into the integrator's browser environment.
The `tableLayout` option defaults to `auto`, except when any column is fixed or uses ellipsis, or when the header is fixed. It can be set to `fixed`, matching CSS table layout behavior described by the linked property documentation. The package does not document a browser support matrix in the README. Consumers should therefore treat exact sticky offsets, fixed-header alignment, and horizontal scrolling as integration points that need verification in their own supported browsers.
Expandable Rows and Virtual Rendering Boundaries
Expansion is configured through the `expandable` object rather than a single boolean. The API supports initial expansion through `defaultExpandAllRows` and `defaultExpandedRowKeys`, controlled expansion through `expandedRowKeys`, and callbacks through `onExpand`, `onExpandAll`, and `onExpandedRowsChange`. Custom expanded content is supplied through `expandedRowRender`, while `rowExpandable` can prevent expansion for particular records.
There are several smaller controls around that behavior. `expandIconColumnIndex` determines where the row icon is inserted, `columnTitle` customizes the expand column title, `expandedRowClassName` styles expanded content, `indentSize` controls nested indentation, and `fixed` can keep the expansion icon in place during horizontal scrolling. `expandRowByClick` allows row clicks to trigger expansion. These options expose state and rendering decisions that a higher-level table component might otherwise choose for the caller.
The documentation also calls out a specific virtual-mode limitation. With `forceRender`, expanded content is rendered before expansion, but in virtual mode only rows mounted by the virtual list are force-rendered. Off-screen rows can remain unmounted. That behavior matters for code that assumes every expanded row's content has already executed, particularly content with registration or measurement side effects. Virtual support is valuable for large datasets, but consumers must account for mounting rather than equating “expanded” with “present in the DOM.”
Installing @rc-component/table and Rendering the First Table
The README gives one installation command for the published package:
npm install @rc-component/tableThis installs the package into the current npm project. The repository documentation does not prescribe a peer dependency command, a global installation, or a particular bundler configuration for the first use.
The first example defines a `User` interface, typed columns, two records, and the default export. Create a TypeScript or TSX component containing the following code:
import Table from '@rc-component/table';
import type { ColumnsType } from '@rc-component/table';
interface User {
key: string;
name: string;
age: number;
address: string;
}
const columns: ColumnsType<User> = [
{ title: 'Name', dataIndex: 'name', key: 'name', width: 120 },
{ title: 'Age', dataIndex: 'age', key: 'age', width: 80 },
{ title: 'Address', dataIndex: 'address', key: 'address' },
];
const data: User[] = [
{ key: '1', name: 'Jack', age: 28, address: 'Somewhere' },
{ key: '2', name: 'Rose', age: 36, address: 'Somewhere else' },
];
export default () => <Table columns={columns} data={data} />;The expected result is a React table with three headers and two rows. The default `rowKey` reads each record's `key` field, so the explicit keys in this example already match that rule. The README does not include an application bootstrap, CSS import, or bundler setup for this example, so those details belong to the consuming React project rather than this short first render.
Developers can run the repository's local dumi documentation with the documented commands:
npm install
npm startThe README says to open `http://localhost:8000` afterward. This is the documented path for viewing the repository examples, not an application integration command.
Component Overrides, Styling, and the Ant Design Boundary
The default container class prefix is `rc-table`, and `className` adds another class to the container. A design system can therefore target the primitive through project CSS while retaining the package's structural classes. The `components` property goes further by allowing table elements to be overridden. The README links this API to repository discussion #171, and the example section does not enumerate every supported replacement.
That missing enumeration is a limitation for adoption decisions. A caller can see that element overrides exist, but the visible API does not establish the full set of supported slots or all properties passed to replacement components. The package is not documented as a styling theme or a complete visual component. Its repository includes Less assets and compilation produces CSS, but the README does not present a theme customization workflow.
Compared with a complete component such as Ant Design Table, @rc-component/table requires more assembly decisions. The higher-level consumer can standardize presentation around the primitive, while applications must decide class naming, visual states, expansion icons, and element composition. That extra work is the reason to use a low-level package, but it becomes unnecessary overhead when the application merely needs a conventional table with predefined styling.
The package also supports specialized hooks such as `title(currentData)`, `footer(currentData)`, and `summary(data)`. These callbacks expose current data for custom regions instead of forcing every table into the same header and footer structure. That supports aggregation or contextual controls, although the README does not prescribe a sorting API, filtering API, pagination API, or server-side data protocol in the shown portion.
Release Cadence, Compatibility, and MIT Licensing
The repository is not archived, and its last push was on 2026-09-14. Recent published versions include `@rc-component/[email protected]` on 2026-08-18, `@rc-component/[email protected]` on 2026-08-03, and `@rc-component/[email protected]` on 2026-07-31. This establishes recent development activity, although repository activity alone does not guarantee compatibility with a particular application configuration.
The package uses a caret range for several `@rc-component` runtime dependencies, including context, resize observer, utility, and virtual-list packages. Consumers installing `@rc-component/table` will resolve compatible versions according to npm and the lockfile used by their project. For repeatable builds, the consuming application's lockfile therefore matters. The repository's own `package.json` declares a Node.js engine range of `>=8.x` for the package, while the development dependencies and tooling shown are from a much newer JavaScript ecosystem.
The package is published with `main` set to `./lib/index`, `module` set to `./es/index`, and TypeScript declarations under `./es/index.d.ts`. Published files include `assets/*.css`, `es`, and `lib`. Consumers can select the appropriate entry through their module system and bundler, but the README does not prescribe a particular bundler setting.
The repository and package metadata identify the license as MIT. That permits use and modification under the license's conditions, but projects should preserve the applicable notices. License handling is especially relevant for internal component libraries and redistributed bundles because the low-level package may appear several layers below the final product.
Editorial conclusion
Adopt @rc-component/table when a product or design system needs controllable React table mechanics beneath its own presentation layer. Do not choose it for a quick styled table unless its low-level API, prefix classes, and styling expectations fit the project. Verify first that your records have stable row keys, that the Node.js environment satisfies package.json, and that the required column widths and scroll settings produce the intended layout.
Frequently asked questions
What is @rc-component/table used for?
It provides low-level React table primitives for typed column and record configuration, fixed headers, scrolling, sticky behavior, expandable rows, summaries, and virtual rendering. It is positioned for composition within design systems and React data display experiences.
How do I install and render a table with @rc-component/table?
Run `npm install @rc-component/table`, define typed columns, create a record array, and pass both to `Table`. The README's first example uses `ColumnsType<User>` and the default `rowKey` field named `key`.
Does @rc-component/table render expanded virtual rows before they are visible?
Not in every virtual case. With `forceRender` enabled, only rows currently mounted by the virtual list are force-rendered, so off-screen rows may remain unmounted.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/react-component-table)Was this useful?