React Native TableView
Native iOS UITableView for React Native with JSON support
<img alt="npm version" src="https://img.shields.io/npm/v/react-native-tableview.svg?style=flat-square">
<img alt="npm downloads" src="https://img.shields.io/npm/dm/react-native-tableview.svg?style=flat-square">
<a href="#badge">
<img alt="code style: prettier" src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square">
Contents
Features
- Look and feel of iOS TableView - because it is! (with group/plain
- Display long lists of data (like country list) with no performance loss
- Built-in accessory types (checkmark or disclosure indicator)
- Pull to refresh!
- Automatic scroll to initial selected value during component initialization
- Automatic item selection with "checkmark" with old item de-selection
- Render Native Section Index Titles (sectionIndexTitlesEnabled property)
- Native JSON support for datasource. If you need to display large dataset,
- Filter JSON datasources using NSPredicate syntax. For example you could select
- Create custom UITableView cells with flexible height using React Native syntax
- Use TableView as menu to navigate to other screens (check included demo, using
- Native editing mode for table - move/delete option is supported by using
Installation
Using npm:npm install react-native-tableview --save
or using yarn:
yarn add react-native-tableview
⚠️ If you are on React Native < 0.60.0, you must use version 2.x.x of this library
Pods
If using CocoaPods or React Native version >= 0.60.0
cd ios && pod install && cd ..
Linking
For React Native <= 0.59 only
react-native link react-native-tableview
If fails, follow manual linking steps below,
Manual Linking
- In XCode, in the project navigator, right click Libraries ➜ Add Files to
[your project's name]
- Add ./nodemodules/react-native-tableview/RNTableView.xcodeproj
- In the XCode project navigator, select your project, select the Build Phases
tab and in the Link Binary With Libraries section add libRNTableView.a
- And in the Build Settings tab in the Search Paths/Header Search Paths section
add \$(SRCROOT)/../node_modules/react-native-tableview (make sure it's
recursive).
Supported Styles
UITableView styles
These values are provided to thetableViewStyle
prop.<TableView tableViewStyle={TableView.Consts.Style.Grouped}>
| Style | Value | Preview | | ------- | -------------------------------- | -------------------------------------------- | | Plain |
TableView.Consts.Style.Plain
| 
TableView.Consts.Style.Grouped
| 
UITableViewCell styles
These values are provided to thetableViewCellStyle
prop.<TableView tableViewCellStyle={TableView.Consts.CellStyle.Default}>
| Style | Value | Preview | | -------- | ------------------------------------- | ---------------------------------------------- | | Default |
TableView.Consts.CellStyle.Default
| 
TableView.Consts.CellStyle.Value1
| 
TableView.Consts.CellStyle.Value2
| 
TableView.Consts.CellStyle.Subtitle
| 
Accessory types
These values are provided to theaccessoryType
prop on the Item
.<Item accessoryType={TableView.Consts.AccessoryType.None}>
| Style | Value | Preview | | -------------------- | ---------------------------------------------------- | --------------------------------------------------------- | | None |
TableView.Consts.AccessoryType.None
| 
TableView.Consts.AccessoryType.DisclosureIndicator
| 
TableView.Consts.AccessoryType.DisclosureButton
| 
TableView.Consts.AccessoryType.Checkmark
| 
TableView.Consts.AccessoryType.DetailButton
| 
Disclosure Indicator can also be applied by adding the
arrow
prop on the
section.<Section arrow>
Checkmark can also be applied by adding the
selected
prop on the Item.<Item selected>
Props
For a full list of props on all components check out the typescript definitions file.Methods
scrollTo()
Scrolls to a set of coordinates on the tableview./**
* @param x Horizontal pixels to scroll
* @param y Vertical pixels to scroll
* @param animated With animation or not
*/
scrollTo(x: number, y: number, animated: boolean): void;
scrollToIndex()
Scroll to an item in a section/**
* @param params scroll params
* @param params.index index of the cell
* @param params.section index of the section @default 0
* @param params.animated scroll with animation @default true
*/
scrollToIndex(params: { index: number, section?: number, animated?: boolean }): void;
List item format
Items in the list can be eitherTableView.Item
or TableView.Cell
. An Item
is simply text. A Cell
can be any complex component. However, only Item
s can
be edited or moved. There are also issues with Cell
s re-rendering on data
changes (#19) that can be avoided by using Item
s. If you want to be able to
re-render, edit or move a complex component, use reactModuleForCell
, described
in Editable Complex Components.Examples
Smooth scrolling with large network loaded list

() => {
const [loading, setLoading] = useState(true);
const [users, setUsers] = useState([]);
useEffect(() => {
const getUsers = async () => {
const response = await fetch('https://randomuser.me/api/?results=5000');
const data = await response.json();
setLoading(false);
setUsers(
data.results.map(a => ({
name: `${a.name.first} ${a.name.last}`,
id: a.registered,
}))
);
};
getUsers();
}, []);
return (
<View style={{ flex: 1 }}>
<Text style={styles.title}>
{loading ? 'Fetching' : 'Fetched'} 5000 users
</Text>
{loading && <ActivityIndicator />}
<TableView
style={{ flex: 1 }}
tableViewCellStyle={TableView.Consts.CellStyle.Subtitle}
>
<Section>
{users.map(a => (
<Item key={a.id}>{a.name}</Item>
))}
</Section>
</TableView>
</View>
);
};
App-bundled JSON with filter and selected value checkmarked

// list spanish provinces and add 'All states' item at the beginning
const country = 'ES';
return (
<View style={{ flex: 1 }}>
<Text style={styles.title}>Showing States in Spain</Text>
<TableView
style={{ flex: 1 }}
json="states"
selectedValue="ES53"
filter={`country=='${country}'`}
tableViewCellStyle={TableView.Consts.CellStyle.Subtitle}
onPress={event => alert(JSON.stringify(event))}
/>
</View>
);
Built-in editing

render() {
return (
<View style={{ flex: 1 }}>
<TableView
style={{ flex: 1 }}
editing={navigation.getParam('editing')}
>
<Section canMove canEdit>
<Item canEdit={false}>Item 1</Item>
<Item>Item 2</Item>
<Item>Item 3</Item>
<Item>Item 4</Item>
<Item>Item 5</Item>
<Item>Item 6</Item>
<Item>Item 7</Item>
<Item>Item 8</Item>
</Section>
</TableView>
</View>
)
}
Pull to Refresh

function reducer(state, action) {
switch (action.type) {
case 'getUsers':
return { ...state, loading: false, users: action.payload };
case 'startRefresh':
return { ...state, refreshing: true };
case 'endRefresh':
return {
...state,
refreshing: false,
amount: state.amount + 10,
users: [...state.users, ...action.payload],
};
default:
return state;
}
}
() => {
const [{ loading, amount, refreshing, users }, dispatch] = useReducer(
reducer,
{
loading: true,
users: [],
refreshing: false,
amount: 10,
}
);
useEffect(() => {
const getUsers = async () => {
const data = await fetchUsers();
dispatch({ type: 'getUsers', payload: data });
};
getUsers();
}, []);
const fetchUsers = async () => {
const response = await fetch('https://randomuser.me/api/?results=10');
const data = await response.json();
return data.results.map(a => ({
name: `${a.name.first} ${a.name.last}`,
id: a.login.uuid,
}));
};
const fetchMore = async () => {
dispatch({ type: 'startRefresh' });
const data = await fetchUsers();
dispatch({ type: 'endRefresh', payload: data });
};
return (
<View style={{ flex: 1 }}>
<Text style={styles.title}>
{loading ? 'Fetching' : 'Fetched'} {amount} users
</Text>
{loading && <ActivityIndicator />}
<TableView
style={{ flex: 1 }}
tableViewCellStyle={TableView.Consts.CellStyle.Subtitle}
canRefresh
refreshing={refreshing}
onRefresh={fetchMore}
>
<Section>
{users.map(a => (
<Item key={a.id}>{a.name}</Item>
))}
</Section>
</TableView>
</View>
);
};
}
Customization
The following style props are supported:tableViewCellStyle
tableViewCellEditingStyle
separatorStyle
contentInset
contentOffset
scrollIndicatorInsets
cellLayoutMargins
cellSeparatorInset
Colors:
textColor
tintColor
selectedTextColor
detailTextColor
separatorColor
headerTextColor
headerBackgroundColor
footerTextColor
Base font:
fontSize
fontWeight
fontStyle
fontFamily
"Subtitle" font:
detailFontSize
detailFontWeight
detailFontStyle
detailFontFamily
Header font:
headerFontSize
headerFontWeight
headerFontStyle
headerFontFamily
Footer font:
footerFontSize
footerFontWeight
footerFontStyle
footerFontFamily
Images / Icons
AnItem
component takes an image
and an optional imageWidth
prop.An
image
prop can be a string pointing to the name of an asset in your "Asset
Catalog". In this case an imageWidth
prop is recommended.<Item image="icon-success.png" imageWidth={40} />
Alternatively, you can
require
the image from your local app code. In this case
an imageWidth
is unnecessary.<Item image={require('../images/icon-success.png')} />
Editable Complex Components
OnlyItem
s can be edited or moved. However you can create a complex component
that is referenced by an Item using reactModuleForCell
. You will need to do
several things to set this up.- Write your view component.
- Pass the name of your view component as a prop in your
<TableView>
component.
- Create a list of
<Item>
s in your TableView, passing props intended for your
view component.
- Register your view component as an
App
root view.
Write your cell view component.
For example,//Should be pure... setState on top-level component doesn't seem to work
class TableViewExampleCell extends React.Component {
render() {
var style = { borderColor: '#aaaaaa', borderWidth: 1, borderRadius: 3 };
// Fill the full native table cell height.
style.flex = 1;
// All Item props get passed to this cell inside this.props.data. Use them to control the rendering, for example background color:
if (this.props.data.backgroundColor !== undefined) {
style.backgroundColor = this.props.data.backgroundColor;
}
return (
<View style={style}>
<Text>
section:{this.props.section},row:{this.props.row},label:
{this.props.data.label}
</Text>
<Text> message:{this.props.data.message}</Text>
</View>
);
}
}
For more examples, see examples/TableViewDemo.
Pass component as prop.
<TableView reactModuleForCell="TableViewExampleCell" >
Create list of items, passing props
<Section canEdit={true}>
{this.props.items.map(function(item) {
return (
<Item
key={'i' + item.data.date}
label={item.label}
message={item.message}
/>
);
})}
</Section>
Note that the props you pass must be primitive types: they cannot be objects. Also, note that the props become properties of the
data
prop in your
reactModuleForCell
component. That is, you pass label="foo"
and in your
component you pick it up as this.props.data.label
.Register your component.
Each cell you render becomes a reuseable root view orApp
.var { AppRegistry } = React;
...
AppRegistry.registerComponent('TableViewExample', () => TableViewExample);
When debugging, you will see the message:
Running application "TableViewExample" with appParams: { /* params */ }. __DEV__ === true, development-level warning are ON, performance optimizations are OFF
multiple times. While slightly annoying, this does not seem to affect performance. You may also see message Unbalanced calls start/end for tag 5.