Many apps conform to a 'list/detail' pattern:
- A list of items is presented on the first screen, with a summary of information (usually a title and optional subtitle).
- Each list item is tappable.
- When tapped, the app navigates to a detail view, showing data from the corresponding item that was tapped.
List: Detail:
____________ ____________
/ \ / \
| Item | | Title |
| ---------- | | Subtitle |
| Item ●--|------> | |
| ---------- | | Here is a |
| Item | | house. |
| ---------- | | |
| Item | | []___ |
| ---------- | | / /\ |
| Item | | /____/__\ |
| ---------- | | |[][]|||| |
| Item | | |
\____________/ \____________/
One way to implement the list is to use a ScrollView
with many individual View
items:
return (
<ScrollView>
<View><Text>1</Text></View>
<View><Text>2</Text></View>
<View><Text>3</Text></View>
<View><Text>4</Text></View>
</ScrollView>
);
Taking this a step further, instead of repeating the JSX we could use an array and map
over it:
const items = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];
return (
<ScrollView>
{items.map((item, index) => (
<View key={index}><Text>{item}</Text></View>
))}
</ScrollView>
);
When rendering a list of items, a better alternative to ScrollView
is available: FlatList
.
import React, { Component } from 'react';
import { View, Text, FlatList } from 'react-native';
class List extends Component {
renderItem({item}) {
return <View><Text>{item}</Text></View>;
}
render() {
const items = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];
return <FlatList data={items} renderItem={this.renderItem} />;
}
}
Similar to a ScrollView
, each item in the FlatList
needs a key:
import React, { Component } from 'react';
import { View, Text, FlatList } from 'react-native';
class List extends Component {
keyExtractor(item, index) {
return `${index}`; // must return a string here.
}
render() {
const items = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];
return (
<FlatList data={items} keyExtractor={this.keyExtractor} />
);
}
}
Use ItemSeparatorComponent
to render a separator between each item:
import React, { Component } from 'react';
import { View, Text, FlatList } from 'react-native';
class List extends Component {
renderSeparator() {
const style = { height: 1, backgroundColor: '#777' };
return <View style={style} />;
}
render() {
return (
<FlatList ItemSeparatorComponent={this.renderSeparator} />
);
}
}
Sometimes, you don't want Text
to wrap when it reaches the end of its container. This is especially true when rendering list items.
You can use the numberOfLines
prop to truncate text after a specific number of lines.
return (
<Text numberOfLines={1}>
Laboris in ea fugiat nisi exercitation ipsum elit incididunt
fugiat cupidatat in. Tempor nisi sint ad non excepteur mollit
sint adipisicing. Laborum ut et culpa dolore elit eiusmod
laborum in ullamco qui qui elit sunt.
</Text>
);
The text will be truncated, and ellipses will be added (...
).
Sometimes we want to conditionally run code depending on the target platform (iOS / Android). We can achieve this using the Platform
module.
import { Platform } from 'react-native';
const isIOS = Platform.OS === 'ios';
const isAndroid = Platform.OS === 'android';
Oftentimes we also want to change styles according to the platform. This is possible with Platform.select()
:
import { Platform } from 'react-native';
const platformStyles = Platform.select({
ios: {
backgroundColor: '#fff'
},
android: {
backgroundColor: '#eee'
}
});
console.log(platformStyles);
// -> on iOS: { backgroundColor: '#fff' }
// -> on Android: { backgroundColor: '#eee' }
We can then apply the styles to a StyleSheet
using the Object spread syntax:
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
// Spread the platformStyles object into this one
...platformStyles
}
});
The above will produce the following styles on iOS:
{
flex: 1,
backgroundColor: '#fff'
}
and the following on Android:
{
flex: 1,
backgroundColor: '#eee'
}
Since much of React Native runs as JavaScript, we can use any JavaScript-based library, provided it does not use any browser APIs.
Install a third party library with npm
:
npm install moment
Then import the library for use as normal:
import React from 'react';
import { Text } from 'react-native';
import moment from 'moment';
const RightNow = ({date}) => (
<Text>{moment(date).calendar()}</Text>
);