npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bestcoder/react-native-data-table

v1.0.5

Published

A high-performance cross-platform data table for React Native and Expo.

Downloads

797

Readme

@bestcoder/react-native-data-table

简体中文 | English

npm version license npm downloads

基于 FlashList v2 的高性能 React Native 数据表格,支持 iOS、Android 和 Web。内置横纵滚动、固定列、自适应列宽、行选择、受控排序、展开行、异步子表、主题与边框配置。

A high-performance, cross-platform data table for React Native, Expo, and React Native Web.

特性

  • FlashList v2 虚拟化,适合大数据列表。
  • 纵向滚动、横向滚动与可关闭的吸顶表头。
  • fixed: 'left' | 'right' 左右固定列。
  • 按真实渲染内容测量自适应列宽,支持 minWidth 和定宽列。
  • 受控行选择、全选/半选、禁用行、自定义 Checkbox 及选择列合并。
  • 受控三态排序:null → ascend → descend → null
  • 自定义展开面板或异步联动子表。
  • 下拉刷新、触底加载、空态、页面级头尾内容。
  • 可配置主题、斑马纹、按压高亮、单元格样式和网格边框。
  • TypeScript 类型声明随包发布。

兼容性

| 环境 | 支持范围 | |---|---| | Expo | SDK 57 | | React Native | >=0.78.0 | | React | >=19.0.0 <20 | | @shopify/flash-list | >=2.2.1 <3 | | Node.js | >=22.13.0 | | 平台 | iOS / Android / Web |

Web 端需要宿主项目已正常配置 React Native Web;Expo 项目默认已包含该能力。

安装

Expo SDK 57

npx expo install @shopify/flash-list
npm install @bestcoder/react-native-data-table

React Native

npm install @bestcoder/react-native-data-table @shopify/flash-list

本包没有自定义原生模块;原生端要求取决于 @shopify/flash-list 和宿主 React Native 项目。

快速上手

DataTable 默认使用 flex: 1,父容器必须有可计算的高度;也可直接传入 heightmaxHeight

import { Text, View } from 'react-native';
import {
  DataTable,
  type TableColumn,
} from '@bestcoder/react-native-data-table';

interface Order {
  id: string;
  customer: string;
  amount: number;
  status: 'paid' | 'pending';
}

const rows: Order[] = [
  { id: 'SO-001', customer: 'Alice', amount: 1280, status: 'paid' },
  { id: 'SO-002', customer: 'Bob', amount: 860, status: 'pending' },
];

const columns: TableColumn<Order>[] = [
  { title: '订单号', dataIndex: 'id', width: 110, fixed: 'left' },
  { title: '客户', dataIndex: 'customer', minWidth: 120 },
  { title: '金额', dataIndex: 'amount', align: 'right', sorter: true },
  { title: '状态', dataIndex: 'status', minWidth: 100 },
];

export function OrderList() {
  return (
    <View style={{ flex: 1 }}>
      <DataTable
        data={rows}
        columns={columns}
        keyExtractor={(item) => item.id}
        striped
        highlightOnRowPress
      />
    </View>
  );
}

核心用法

受控排序

组件只输出排序意图,不会修改 data。调用方需根据 currentSort 排序数据后再传回。

const [sort, setSort] = useState<SortParams>();
const sortedRows = useMemo(() => sortRows(rows, sort), [rows, sort]);

<DataTable
  data={sortedRows}
  columns={columns}
  keyExtractor={(item) => item.id}
  currentSort={sort}
  onSort={setSort}
/>

行选择

rowSelection 是受控配置。不传时不渲染选择列。

const tableRef = useRef<DataTableHandle>(null);
const [selectedKeys, setSelectedKeys] = useState<string[]>([]);

<DataTable
  ref={tableRef}
  data={rows}
  columns={columns}
  keyExtractor={(item) => item.id}
  rowSelection={{
    selectedRowKeys: selectedKeys,
    onChange: (keys) => setSelectedKeys(keys),
    getCheckboxProps: (record) => ({ disabled: record.status === 'paid' }),
    position: 'first',
  }}
/>

tableRef.current?.selectAll();
tableRef.current?.clearSelection();
tableRef.current?.scrollToTop();

展开行

custom 是默认模式。展开内容占满当前视口宽度,不跟随主表横向滚动。

<DataTable
  data={rows}
  columns={columns}
  keyExtractor={(item) => item.id}
  renderExpandedRow={(record) => (
    <View style={{ padding: 16 }}>
      <Text>订单:{record.id}</Text>
    </View>
  )}
/>

异步子表

sub-table 模式先通过 onExpandFetch 获取子数据,再由 getSubTable 返回子表规格。子表没有表头,但可与父表共享横向滚动、固定列和最终列宽。

<DataTable<Order, LineItem[]>
  data={rows}
  columns={columns}
  keyExtractor={(item) => item.id}
  expandedRowType="sub-table"
  onExpandFetch={(order) => fetchLineItems(order.id)}
  getSubTable={(_order, _index, items) => ({
    rows: items,
    columns: [
      { colIndex: 0, dataIndex: 'sku' },
      { colIndex: 1, dataIndex: 'name' },
      { colIndex: 2, dataIndex: 'quantity', align: 'right' },
    ],
  })}
/>
  • SubColumn.colIndex 按父表视觉列顺序对齐,包含内部选择列和固定列归位后的顺序。
  • colSpan 可横跨多个父列。
  • Loading、Error 和 Empty 有默认面板,均可自定义。
  • subTableSyncScrollsubTableSyncFixedColumns 默认都为 true

主题

theme 接受 Partial<DataTableTheme>,与内置主题合并。只需覆盖要修改的 token。

<DataTable
  data={rows}
  columns={columns}
  keyExtractor={(item) => item.id}
  theme={{
    primary: '#6D5EF7',
    primaryLight: '#EFEDFF',
    headerBg: '#F8F7FF',
  }}
/>

| Token | 用途 | |---|---| | headerBg | 表头、展开区和斑马纹奇数行默认背景 | | rowBg | 数据行、Checkbox 和斑马纹偶数行默认背景 | | text | 主文字 | | textSecondary | 次级文字、错误和空态 | | primary | Checkbox、排序激活态和 Loading | | primaryLight | 默认行按压高亮 | | onPrimary | 主色上的对勾/半选标记 | | line | 默认边框颜色 | | disabled | Checkbox 和排序禁用/未激活态 |

也可导入 DEFAULT_DATA_TABLE_THEME 作为完整基线。

边框

<DataTable
  data={rows}
  columns={columns}
  keyExtractor={(item) => item.id}
  border={{
    horizontal: true,
    vertical: true,
    outer: true,
    color: '#D7D9E0',
    width: 1,
  }}
/>
  • 省略 border:只开启默认横向分隔线。
  • false:关闭全部边框。
  • true:开启默认横向分隔线。
  • 对象:通过 horizontalverticaloutercolorwidth 组合配置。

API

DataTableProps<T, D>

| Prop | 类型 | 默认值 | 说明 | |---|---|---|---| | data | T[] | 必填 | 原始数据源 | | columns | TableColumn<T>[] | 必填 | 列配置 | | keyExtractor | (item, index) => string | 必填 | 返回全局唯一且稳定的行 key | | remeasureKey | string \| number | — | 变化时原地重新测量自适应列 | | height | DimensionValue | — | 固定表格高度,优先于 maxHeight | | maxHeight | DimensionValue | — | 父 flex 布局中的最大高度 | | striped | boolean | false | 开启斑马纹 | | stripeColors | [string, string] | [theme.rowBg, theme.headerBg] | 偶数/奇数行背景 | | highlightOnRowPress | boolean | false | 按下行时高亮 | | highlightColor | string | theme.primaryLight | 行按压高亮色 | | rowSelection | RowSelectionConfig<T> | — | 受控行选择配置;开关选择模式或切换合并宿主列时会自动原地重测列宽 | | stickyHeader | boolean | true | 表头吸顶开关 | | ref | Ref<DataTableHandle> | — | 命令式句柄:行选择与纵/横向滚动方法,见 DataTableHandle | | onSort | (params: SortParams) => void | — | 排序状态变化回调 | | currentSort | SortParams | — | 当前受控排序状态 | | renderSortIcon | (order) => ReactNode | — | 全局自定义排序图标,三态宽度应保持一致 | | refreshing | boolean | — | 下拉刷新状态 | | onRefresh | () => void | — | 下拉刷新回调 | | onEndReached | () => void | — | 触底加载回调 | | onEndReachedThreshold | number | — | FlashList 触底阈值 | | ListHeaderComponent | ComponentType \| ReactElement \| null | — | 只跟随纵向滚动的页面级头部 | | ListFooterComponent | ComponentType \| ReactElement \| null | — | 只跟随纵向滚动的页面级尾部 | | ListEmptyComponent | ComponentType \| ReactElement \| null | — | data 为空时渲染 | | expandedRowType | 'custom' \| 'sub-table' | 'custom' | 展开行模式 | | expandedRowStyle | StyleProp<ViewStyle> | — | 展开区容器样式 | | renderExpandedRow | (record, index, columnWidths, subData?) => ReactNode | — | 自定义展开内容 | | onExpandFetch | (record, index) => Promise<D> | — | 展开时异步获取数据,按行 key 缓存 | | getSubTable | (record, index, subData) => SubTableSpec | — | 将子数据转换为子表规格 | | isExpandedDataEmpty | (subData) => boolean | 内置判空 | 自定义子数据判空 | | renderExpandedLoading | (columnWidths) => ReactNode | 内置 Loading | 自定义加载面板 | | renderExpandedError | (error, retry, columnWidths) => ReactNode | 内置可重试错误面板 | 自定义错误面板 | | renderExpandedEmpty | (columnWidths) => ReactNode | 内置空面板 | 自定义空数据面板 | | subTableSyncScroll | boolean | true | 子表与父表横向滚动联动 | | subTableSyncFixedColumns | boolean | true | 子表同步父表固定列 | | expandAnimationDuration | number | 200 | 展开/折叠过渡动画时长(ms),传 0 关闭动画 | | onRowPress | (record, index) => void | — | 行点击回调(横向拖动不触发);与展开行共存时先回调再切换展开 | | style | StyleProp<ViewStyle> | — | 最外层容器样式 | | headerStyle | StyleProp<ViewStyle> | — | 表头行样式 | | headerTextStyle | StyleProp<TextStyle> | — | 全局表头文字样式 | | rowStyle | StyleProp<ViewStyle> | — | 数据行样式 | | cellStyle | StyleProp<ViewStyle> | — | 全局单元格基础样式 | | cellTextStyle | StyleProp<TextStyle> | — | 默认单元格文字样式 | | border | boolean \| DataTableBorder | 横向分隔线 | 边框配置 | | theme | Partial<DataTableTheme> | 内置主题 | 覆盖主题 token |

T 是父行数据类型,DonExpandFetch 返回的子数据类型,默认为 unknown

TableColumn<T>

| 字段 | 类型 | 说明 | |---|---|---| | title | string | 默认表头标题 | | dataIndex | keyof T \| string | 无 render 时用于读取单元格值 | | width | number | 固定列宽,跳过内容测量和弹性分配 | | minWidth | number | 自适应列的最小宽度 | | align | 'left' \| 'center' \| 'right' | 单元格和表头对齐,默认 left | | fixed | 'left' \| 'right' | 左/右固定列 | | sorter | boolean | 启用表头排序交互 | | cellStyle | StyleProp<ViewStyle> | 列样式,同时影响表头和数据单元格 | | renderCellStyle | (record, index) => StyleProp<ViewStyle> | 数据单元格动态样式,优先级最高 | | render | (record, index) => ReactNode | 自定义数据单元格 | | renderHeader | () => ReactNode | 自定义表头内容,优先于 title | | headerCellStyle | StyleProp<ViewStyle> | 仅表头单元格样式 | | headerTextStyle | StyleProp<TextStyle> | 仅默认表头文字样式 |

样式优先级:

  • 数据单元格:内置基础样式 → 全局 cellStyle → 列 cellStylerenderCellStyle
  • 表头单元格:内置基础样式 → 全局 cellStyle → 列 cellStyleheaderCellStyle
  • 表头文字:内置文字样式 → 全局 headerTextStyle → 列 headerTextStyle

RowSelectionConfig<T>

| 字段 | 类型 | 默认值 | 说明 | |---|---|---|---| | selectedRowKeys | string[] | 必填 | 当前选中 key | | onChange | (keys, rows) => void | 必填 | 按 data 顺序返回 key 和行数据 | | getCheckboxProps | (record) => { disabled?: boolean } | — | 按行禁用选择 | | position | 'first' \| 'last' | 'first' | 独立选择列位置,自动归入对应固定列组 | | renderCheckbox | (selected, record) => ReactNode | 内置 Checkbox | 自定义行选择框内容 | | renderHeaderCheckbox | ({ checked, indeterminate, disabled }) => ReactNode | 内置 Checkbox | 自定义全选/半选内容 | | mergeIntoDataIndex | string | — | 将选择框合并进指定 dataIndex 列 | | checkboxAlign | 'top' \| 'center' \| 'bottom' | 'center' | 合并模式的垂直对齐 |

SubColumn<S>SubTableSpec<S>

SubColumn<S>

| 字段 | 类型 | 说明 | |---|---|---| | colIndex | number | 对齐父表视觉列顺序的下标 | | colSpan | number | 横跨父列数,默认 1 | | dataIndex | keyof S \| string | 无 render 时读取子行字段 | | align | 'left' \| 'center' \| 'right' | 默认继承对应父列 | | cellStyle | StyleProp<ViewStyle> | 子列基础样式 | | renderCellStyle | (row, index) => StyleProp<ViewStyle> | 子单元格动态样式 | | render | (row, index) => ReactNode | 自定义子单元格 |

SubTableSpec<S>

| 字段 | 类型 | 说明 | |---|---|---| | rows | S[] | 子表行数据 | | columns | SubColumn<S>[] | 子列配置 | | rowStyle | StyleProp<ViewStyle> | 子表行样式 | | cellStyle | StyleProp<ViewStyle> | 全局子单元格样式 | | cellTextStyle | StyleProp<TextStyle> | 默认子单元格文字样式 |

DataTableBorder

| 字段 | 类型 | 默认值 | 说明 | |---|---|---|---| | color | string | theme.line | 边框颜色 | | width | number | StyleSheet.hairlineWidth | 边框宽度 | | horizontal | boolean | true | 行分隔线 | | vertical | boolean | false | 列分隔线 | | outer | boolean | false | 表格外边框 |

其他公开类型

DataTableHandle

| 方法 | 说明 | |---|---| | selectAll | 全选所有未禁用行;已选中的禁用行保持不变 | | clearSelection | 清空可选行;禁用行的已选状态保留 | | scrollToTop(animated?) | 纵向滚动回顶部;适用于筛选后数据变短导致滚动偏移越界的场景 | | scrollToIndex(index, animated?) | 纵向滚动到指定数据行;下标基于当前已上屏数据(测绘扣留中的行不计入) | | scrollToEnd(animated?) | 纵向滚动到底部 | | scrollToLeft | 横向滚动归零,表头与所有行同步回到最左侧 |

SortParams

| 字段 | 类型 | 说明 | |---|---|---| | dataIndex | string | 排序列的 dataIndex | | order | 'ascend' \| 'descend' \| null | 目标排序方向;null 表示取消排序 |

公开导出

export { DataTable, DEFAULT_DATA_TABLE_THEME };
export type {
  DataTableBorder,
  DataTableHandle,
  DataTableProps,
  DataTableTheme,
  RowSelectionConfig,
  SortParams,
  SubColumn,
  SubTableSpec,
  TableColumn,
};

使用注意事项

  • keyExtractor 必须返回全局唯一、稳定的字符串,不要使用可变数组下标。
  • 未传 height / maxHeight 时,父容器必须有明确高度。
  • 排序、行选择均为受控能力,组件不会自动排序 data 或持久化选中状态。
  • 自定义 renderrenderHeader 和 Checkbox 的各个状态应尽量保持稳定尺寸,避免列宽抖动。
  • 自适应列会真实挂载内容进行离屏测量;高成本自定义单元格建议设置明确 width 或简化测量期渲染。
  • onEndReached 在首次测量或原地重测期间会被暂时屏蔽,以避免重复翻页。
  • 子表的 colIndex 是父表最终视觉列顺序,不一定等于原始 columns 下标。
  • Web 端的固定列依赖 React Native Web 对 CSS position: sticky 的支持。

License

MIT © bestcoder。标准许可证文本已包含在 npm 包的 LICENSE 文件中;版本变化参见 CHANGELOG.md