{"id":3965,"url":"https://github.com/aksonov/react-native-tableview","last_synced_at":"2025-05-15T03:03:11.507Z","repository":{"id":36652925,"uuid":"40959227","full_name":"aksonov/react-native-tableview","owner":"aksonov","description":"Native iOS UITableView for React Native with JSON support and more","archived":false,"fork":false,"pushed_at":"2022-01-24T11:08:05.000Z","size":3939,"stargazers_count":1422,"open_issues_count":27,"forks_count":185,"subscribers_count":27,"default_branch":"master","last_synced_at":"2025-05-12T11:44:58.253Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aksonov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-18T08:10:28.000Z","updated_at":"2025-05-09T15:08:56.000Z","dependencies_parsed_at":"2022-09-16T07:50:53.814Z","dependency_job_id":null,"html_url":"https://github.com/aksonov/react-native-tableview","commit_stats":null,"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aksonov%2Freact-native-tableview","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aksonov%2Freact-native-tableview/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aksonov%2Freact-native-tableview/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aksonov%2Freact-native-tableview/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aksonov","download_url":"https://codeload.github.com/aksonov/react-native-tableview/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254264737,"owners_count":22041791,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-01-05T20:16:56.752Z","updated_at":"2025-05-15T03:03:11.462Z","avatar_url":"https://github.com/aksonov.png","language":"Objective-C","readme":"\u003ch2 align=\"center\"\u003eReact Native TableView\u003c/h2\u003e\n\n\u003cp align=\"center\"\u003eNative iOS UITableView for React Native with JSON support\u003c/a\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/react-native-tableview\"\u003e\n    \u003cimg alt=\"npm version\" src=\"https://img.shields.io/npm/v/react-native-tableview.svg?style=flat-square\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/react-native-tableview\"\u003e\n    \u003cimg alt=\"npm downloads\" src=\"https://img.shields.io/npm/dm/react-native-tableview.svg?style=flat-square\"\u003e\n  \u003c/a\u003e\n   \u003ca href=\"#badge\"\u003e\n    \u003cimg alt=\"code style: prettier\" src=\"https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## Contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Styles](#supported-styles)\n- [Examples](#examples)\n- [Customization](#customization)\n\n## Features\n\n- Look and feel of iOS TableView - **because it is!** (with group/plain\n  tableview type, sections headers, etc)\n- Display long lists of data (like country list) with no performance loss\n- Built-in accessory types (checkmark or disclosure indicator)\n- Pull to refresh!\n- Automatic scroll to initial selected value during component initialization\n  (autoFocus property)\n- Automatic item selection with \"checkmark\" with old item de-selection\n  (optionally), see demo, useful to select country/state/etc.\n- Render Native Section Index Titles (sectionIndexTitlesEnabled property)\n- Native JSON support for datasource. If you need to display large dataset,\n  generated Javascript will became very large and impact js loading time. To\n  solve this problem the component could read JSON directly from app bundle\n  without JS!\n- Filter JSON datasources using NSPredicate syntax. For example you could select\n  states for given country only (check demo)\n- Create custom UITableView cells with flexible height using React Native syntax\n  (TableView.Cell tag)\n- Use TableView as menu to navigate to other screens (check included demo, using\n  react-navigation https://reactnavigation.org)\n- Native editing mode for table - move/delete option is supported by using\n  attributes canMove, canEdit for items/sections\n\n## Installation\n\nUsing npm:\n\n```bash\nnpm install react-native-tableview --save\n```\n\nor using yarn:\n\n```bash\nyarn add react-native-tableview\n```\n\n\u003e ⚠️ If you are on React Native \u003c 0.60.0, you must use version 2.x.x of this library\n\n### Pods\n\n\u003e If using CocoaPods or React Native version \u003e= 0.60.0\n\n```bash\ncd ios \u0026\u0026 pod install \u0026\u0026 cd ..\n```\n\n### Linking\n\n\u003e For React Native \u003c= 0.59 only\n\n```bash\nreact-native link react-native-tableview\n```\n\nIf fails, follow manual linking steps below,\n\n#### Manual Linking\n\n1. In XCode, in the project navigator, right click Libraries ➜ Add Files to\n   [your project's name]\n2. Add ./node_modules/react-native-tableview/RNTableView.xcodeproj\n3. In the XCode project navigator, select your project, select the Build Phases\n   tab and in the Link Binary With Libraries section add libRNTableView.a\n4. And in the Build Settings tab in the Search Paths/Header Search Paths section\n   add \\$(SRCROOT)/../node_modules/react-native-tableview (make sure it's\n   recursive).\n\n## Supported Styles\n\n### UITableView styles\n\nThese values are provided to the `tableViewStyle` prop.\n\n```jsx\n\u003cTableView tableViewStyle={TableView.Consts.Style.Grouped}\u003e\n```\n\n| Style   | Value                            | Preview                                      |\n| ------- | -------------------------------- | -------------------------------------------- |\n| Plain   | `TableView.Consts.Style.Plain`   | ![alt text](./.github/tableview-plain.png)   |\n| Grouped | `TableView.Consts.Style.Grouped` | ![alt text](./.github/tableview-grouped.png) |\n\n### UITableViewCell styles\n\nThese values are provided to the `tableViewCellStyle` prop.\n\n```jsx\n\u003cTableView tableViewCellStyle={TableView.Consts.CellStyle.Default}\u003e\n```\n\n| Style    | Value                                 | Preview                                        |\n| -------- | ------------------------------------- | ---------------------------------------------- |\n| Default  | `TableView.Consts.CellStyle.Default`  | ![alt text](./.github/cell-style-default.png)  |\n| Value1   | `TableView.Consts.CellStyle.Value1`   | ![alt text](./.github/cell-style-value1.png)   |\n| Value2   | `TableView.Consts.CellStyle.Value2`   | ![alt text](./.github/cell-style-value2.png)   |\n| Subtitle | `TableView.Consts.CellStyle.Subtitle` | ![alt text](./.github/cell-style-subtitle.png) |\n\n### Accessory types\n\nThese values are provided to the `accessoryType` prop on the `Item`.\n\n```jsx\n\u003cItem accessoryType={TableView.Consts.AccessoryType.None}\u003e\n```\n\n| Style                | Value                                                | Preview                                                   |\n| -------------------- | ---------------------------------------------------- | --------------------------------------------------------- |\n| None                 | `TableView.Consts.AccessoryType.None`                | ![alt text](./.github/accessory-none.png)                 |\n| Disclosure Indicator | `TableView.Consts.AccessoryType.DisclosureIndicator` | ![alt text](./.github/accessory-disclosure-indicator.png) |\n| Disclosure Button    | `TableView.Consts.AccessoryType.DisclosureButton`    | ![alt text](./.github/accessory-disclosure-button.png)    |\n| Checkmark            | `TableView.Consts.AccessoryType.Checkmark`           | ![alt text](./.github/accessory-checkmark.png)            |\n| Detail Button        | `TableView.Consts.AccessoryType.DetailButton`        | ![alt text](./.github/accessory-detail-button.png)        |\n\nDisclosure Indicator can also be applied by adding the `arrow` prop on the\nsection.\n\n```jsx\n\u003cSection arrow\u003e\n```\n\nCheckmark can also be applied by adding the `selected` prop on the Item.\n\n```jsx\n\u003cItem selected\u003e\n```\n\n### Props\n\nFor a full list of props on all components check out\n[the typescript definitions file](./src/index.d.ts).\n\n### Methods\n\n#### `scrollTo()`\n\nScrolls to a set of coordinates on the tableview.\n\n```ts\n/**\n  * @param x Horizontal pixels to scroll\n  * @param y Vertical pixels to scroll\n  * @param animated With animation or not\n  */\n  scrollTo(x: number, y: number, animated: boolean): void;\n```\n\n#### `scrollToIndex()`\n\nScroll to an item in a section\n\n```ts\n/**\n  * @param params scroll params\n  * @param params.index index of the cell\n  * @param params.section index of the section @default 0\n  * @param params.animated scroll with animation @default true\n  */\n  scrollToIndex(params: { index: number, section?: number, animated?: boolean }): void;\n```\n\n### List item format\n\nItems in the list can be either `TableView.Item` or `TableView.Cell`. An `Item`\nis simply text. A `Cell` can be any complex component. However, only `Item`s can\nbe edited or moved. There are also issues with `Cell`s re-rendering on data\nchanges (#19) that can be avoided by using `Item`s. If you want to be able to\nre-render, edit or move a complex component, use `reactModuleForCell`, described\nin [Editable Complex Components](#editable-complex-components).\n\n## Examples\n\n### Smooth scrolling with large network loaded list\n\n![demo-3](./.github/large-network-example.gif)\n\n```jsx\n() =\u003e {\n  const [loading, setLoading] = useState(true);\n  const [users, setUsers] = useState([]);\n\n  useEffect(() =\u003e {\n    const getUsers = async () =\u003e {\n      const response = await fetch('https://randomuser.me/api/?results=5000');\n      const data = await response.json();\n\n      setLoading(false);\n      setUsers(\n        data.results.map(a =\u003e ({\n          name: `${a.name.first} ${a.name.last}`,\n          id: a.registered,\n        }))\n      );\n    };\n\n    getUsers();\n  }, []);\n\n  return (\n    \u003cView style={{ flex: 1 }}\u003e\n      \u003cText style={styles.title}\u003e\n        {loading ? 'Fetching' : 'Fetched'} 5000 users\n      \u003c/Text\u003e\n\n      {loading \u0026\u0026 \u003cActivityIndicator /\u003e}\n\n      \u003cTableView\n        style={{ flex: 1 }}\n        tableViewCellStyle={TableView.Consts.CellStyle.Subtitle}\n      \u003e\n        \u003cSection\u003e\n          {users.map(a =\u003e (\n            \u003cItem key={a.id}\u003e{a.name}\u003c/Item\u003e\n          ))}\n        \u003c/Section\u003e\n      \u003c/TableView\u003e\n    \u003c/View\u003e\n  );\n};\n```\n\n### App-bundled JSON with filter and selected value checkmarked\n\n![editing example](./.github/bundled-json-example.gif)\n\n```jsx\n// list spanish provinces and add 'All states' item at the beginning\n\nconst country = 'ES';\n\nreturn (\n  \u003cView style={{ flex: 1 }}\u003e\n    \u003cText style={styles.title}\u003eShowing States in Spain\u003c/Text\u003e\n    \u003cTableView\n      style={{ flex: 1 }}\n      json=\"states\"\n      selectedValue=\"ES53\"\n      filter={`country=='${country}'`}\n      tableViewCellStyle={TableView.Consts.CellStyle.Subtitle}\n      onPress={event =\u003e alert(JSON.stringify(event))}\n    /\u003e\n  \u003c/View\u003e\n);\n```\n\n### Built-in editing\n\n![editing example](./.github/editing-example.gif)\n\n```jsx\nrender() {\n  return (\n    \u003cView style={{ flex: 1 }}\u003e\n      \u003cTableView\n        style={{ flex: 1 }}\n        editing={navigation.getParam('editing')}\n      \u003e\n        \u003cSection canMove canEdit\u003e\n          \u003cItem canEdit={false}\u003eItem 1\u003c/Item\u003e\n          \u003cItem\u003eItem 2\u003c/Item\u003e\n          \u003cItem\u003eItem 3\u003c/Item\u003e\n          \u003cItem\u003eItem 4\u003c/Item\u003e\n          \u003cItem\u003eItem 5\u003c/Item\u003e\n          \u003cItem\u003eItem 6\u003c/Item\u003e\n          \u003cItem\u003eItem 7\u003c/Item\u003e\n          \u003cItem\u003eItem 8\u003c/Item\u003e\n        \u003c/Section\u003e\n      \u003c/TableView\u003e\n    \u003c/View\u003e\n  )\n}\n```\n\n### Pull to Refresh\n\n![pull to refresh example](./.github/pull-to-refresh-example.gif)\n\n```jsx\nfunction reducer(state, action) {\n  switch (action.type) {\n    case 'getUsers':\n      return { ...state, loading: false, users: action.payload };\n    case 'startRefresh':\n      return { ...state, refreshing: true };\n    case 'endRefresh':\n      return {\n        ...state,\n        refreshing: false,\n        amount: state.amount + 10,\n        users: [...state.users, ...action.payload],\n      };\n    default:\n      return state;\n  }\n}\n\n() =\u003e {\n  const [{ loading, amount, refreshing, users }, dispatch] = useReducer(\n    reducer,\n    {\n      loading: true,\n      users: [],\n      refreshing: false,\n      amount: 10,\n    }\n  );\n\n  useEffect(() =\u003e {\n    const getUsers = async () =\u003e {\n      const data = await fetchUsers();\n      dispatch({ type: 'getUsers', payload: data });\n    };\n\n    getUsers();\n  }, []);\n\n  const fetchUsers = async () =\u003e {\n    const response = await fetch('https://randomuser.me/api/?results=10');\n    const data = await response.json();\n\n    return data.results.map(a =\u003e ({\n      name: `${a.name.first} ${a.name.last}`,\n      id: a.login.uuid,\n    }));\n  };\n\n  const fetchMore = async () =\u003e {\n    dispatch({ type: 'startRefresh' });\n    const data = await fetchUsers();\n    dispatch({ type: 'endRefresh', payload: data });\n  };\n\n  return (\n    \u003cView style={{ flex: 1 }}\u003e\n      \u003cText style={styles.title}\u003e\n        {loading ? 'Fetching' : 'Fetched'} {amount} users\n      \u003c/Text\u003e\n\n      {loading \u0026\u0026 \u003cActivityIndicator /\u003e}\n\n      \u003cTableView\n        style={{ flex: 1 }}\n        tableViewCellStyle={TableView.Consts.CellStyle.Subtitle}\n        canRefresh\n        refreshing={refreshing}\n        onRefresh={fetchMore}\n      \u003e\n        \u003cSection\u003e\n          {users.map(a =\u003e (\n            \u003cItem key={a.id}\u003e{a.name}\u003c/Item\u003e\n          ))}\n        \u003c/Section\u003e\n      \u003c/TableView\u003e\n    \u003c/View\u003e\n  );\n};\n}\n```\n\n## Customization\n\nThe following style props are supported:\n\n- `tableViewCellStyle`\n- `tableViewCellEditingStyle`\n- `separatorStyle`\n- `contentInset`\n- `contentOffset`\n- `scrollIndicatorInsets`\n- `cellLayoutMargins`\n- `cellSeparatorInset`\n\nColors:\n\n- `textColor`\n- `tintColor`\n- `selectedTextColor`\n- `detailTextColor`\n- `separatorColor`\n- `headerTextColor`\n- `headerBackgroundColor`\n- `footerTextColor`\n\nBase font:\n\n- `fontSize`\n- `fontWeight`\n- `fontStyle`\n- `fontFamily`\n\n\"Subtitle\" font:\n\n- `detailFontSize`\n- `detailFontWeight`\n- `detailFontStyle`\n- `detailFontFamily`\n\nHeader font:\n\n- `headerFontSize`\n- `headerFontWeight`\n- `headerFontStyle`\n- `headerFontFamily`\n\nFooter font:\n\n- `footerFontSize`\n- `footerFontWeight`\n- `footerFontStyle`\n- `footerFontFamily`\n\n## Images / Icons\n\nAn `Item` component takes an `image` and an optional `imageWidth` prop.\n\nAn `image` prop can be a string pointing to the name of an asset in your \"Asset\nCatalog\". In this case an `imageWidth` prop is recommended.\n\n```jsx\n\u003cItem image=\"icon-success.png\" imageWidth={40} /\u003e\n```\n\nAlternatively, you can `require` the image from your local app code. In this case\nan `imageWidth` is unnecessary.\n\n```jsx\n\u003cItem image={require('../images/icon-success.png')} /\u003e\n```\n\n### Editable Complex Components\n\nOnly `Item`s can be edited or moved. However you can create a complex component\nthat is referenced by an Item using `reactModuleForCell`. You will need to do\nseveral things to set this up.\n\n1. Write your view component.\n2. Pass the name of your view component as a prop in your `\u003cTableView\u003e`\n   component.\n3. Create a list of `\u003cItem\u003e`s in your TableView, passing props intended for your\n   view component.\n4. Register your view component as an `App` root view.\n\n### Write your cell view component.\n\nFor example,\n\n```jsx\n//Should be pure... setState on top-level component doesn't seem to work\n\nclass TableViewExampleCell extends React.Component {\n  render() {\n    var style = { borderColor: '#aaaaaa', borderWidth: 1, borderRadius: 3 };\n\n    // Fill the full native table cell height.\n    style.flex = 1;\n\n    // All Item props get passed to this cell inside this.props.data. Use them to control the rendering, for example background color:\n    if (this.props.data.backgroundColor !== undefined) {\n      style.backgroundColor = this.props.data.backgroundColor;\n    }\n\n    return (\n      \u003cView style={style}\u003e\n        \u003cText\u003e\n          section:{this.props.section},row:{this.props.row},label:\n          {this.props.data.label}\n        \u003c/Text\u003e\n        \u003cText\u003e message:{this.props.data.message}\u003c/Text\u003e\n      \u003c/View\u003e\n    );\n  }\n}\n```\n\nFor more examples, see examples/TableViewDemo.\n\n#### Pass component as prop.\n\n```jsx\n\u003cTableView reactModuleForCell=\"TableViewExampleCell\" \u003e\n```\n\n#### Create list of items, passing props\n\n```jsx\n\u003cSection canEdit={true}\u003e\n  {this.props.items.map(function(item) {\n    return (\n      \u003cItem\n        key={'i' + item.data.date}\n        label={item.label}\n        message={item.message}\n      /\u003e\n    );\n  })}\n\u003c/Section\u003e\n```\n\nNote that the props you pass must be primitive types: they cannot be objects.\nAlso, note that the props become properties of the `data` prop in your\n`reactModuleForCell` component. That is, you pass `label=\"foo\"` and in your\ncomponent you pick it up as `this.props.data.label`.\n\n#### Register your component.\n\nEach cell you render becomes a reuseable root view or `App`.\n\n```js\nvar { AppRegistry } = React;\n\n...\n\nAppRegistry.registerComponent('TableViewExample', () =\u003e TableViewExample);\n```\n\nWhen debugging, you will see the message:\n\n```\nRunning application \"TableViewExample\" with appParams: { /* params */ }. __DEV__ === true, development-level warning are ON, performance optimizations are OFF\n```\n\nmultiple times. While slightly annoying, this does not seem to affect\nperformance. You may also see message\n[Unbalanced calls start/end for tag 5](https://github.com/facebook/react-native/issues/4163).\n","funding_links":[],"categories":["Components","组件","\u003ca name=\"UI:-Native-Modules\"\u003eUI: Native Modules\u003c/a\u003e","Others","Objective-C"],"sub_categories":["UI","ListView\u0026ScrollView"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faksonov%2Freact-native-tableview","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faksonov%2Freact-native-tableview","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faksonov%2Freact-native-tableview/lists"}