In addition to the TextInput component, there are a number of other input components that can be used to capture different types of user inputs. We won't be using them yet in our application, but it behooves you to know what they are and when to use them.
A Slider component can be used to capture number within a finite range. For instance, this could be used to select a percent satisfaction (a number between 0 and 1) on a user feedback survey. Take a look at the following screenshot:
The Switch component is used to capture a Boolean, on or off, choice. This type of input could be used to opt out of push notifications within our application. Take a look at the following screenshot:
The Picker component is an interesting one in that, though it is used for both platforms, its appearance is completely different on iOS and Android. This component is analogous to an HTML select component and is used for selecting from a list of discrete options. For
instance, this type of input would be used to select the country in which the user lives.
Native APIs
Some native functionality does not fit nicely into a component. For these things, React Native also exposes several Native APIs that can be used in an application. Some of these we've talked about already in previous chapters. For instance, in Chapter 3, Styling and
Layout in React Native, we introduced the StyleSheet API, which allows us to create
stylesheets for our components. Others we'll cover in depth in future chapters on animation, fetching data, and performance optimization. Aside from these, there are a few that are of interest to us and our application right now.
ActionSheetIOS
In iOS applications, we often show context menus in the form of action sheets. These provide the user with nested options for a particular item on screen. In our application, we will use the ActionSheetIOS API to show the user a context menu that allows them to bookmark a NewsItem when they long press on the NewsItem itself, as shown in the following screenshot:
In order to do this, the first thing we'll need to do is create a listener for the long press event, bind it to the this context in the constructor of the NewsItem, and attach it to the TouchableOpacity element of NewsItem, as shown in the following code:
export default class NewsItem extends Component { constructor(props) {
super(props);
this.onLongPress = this.onLongPress.bind(this); }
onLongPress() {
// Open action sheet } render() { const { style, imageUrl, title, author, date, location, description, onPress } = this.props;
const accentColor = globalStyles.ACCENT_COLORS[
this.props.index % globalStyles.ACCENT_COLORS.length ]; return ( <TouchableOpacity style={style} onPress={onPress} onLongPress={this.onLongPress} > <View> <Thumbnail url={imageUrl} titleText={title} accentColor={accentColor} style={styles.thumbnail} /> <View style={styles.content}> <Byline author={author} date={date} location={location}
/> <AppText> {description} </AppText> </View> </View> </TouchableOpacity> ); } }
Next, we need to import the ActionSheetIOS API and use its showActionSheetWithOptions method to open the context menu:
import { View, TouchableOpacity, StyleSheet, ActionSheetIOS } from 'react-native';
Here, we'll modify our newly created onLongPress method: onLongPress() {
ActionSheetIOS.showActionSheetWithOptions({
options: ['Bookmark', 'Cancel'], cancelButtonIndex: 1,
title: this.props.title
}, buttonIndex => console.log('Button selected', buttonIndex));
}
As we can see, the showActionSheetWithOptions method takes two arguments. The first argument is a JavaScript object with several entries:
{
options: ['Bookmark', 'Cancel'], cancelButtonIndex: 1,
title: this.props.title }
The options value is an array of strings that will be displayed on the buttons that make up the action sheet. Here, we are specifying that we want two buttons, the first says Bookmark and the second Cancel:
We can also tell the action sheet which button is used for canceling the interaction so that it can treat it different visually. In the case of cancel buttons, iOS separates them from the other buttons. Our cancel button is at index 1 in the array:
cancelButtonIndex: 1
Finally, we can optionally add a title to the action sheet that is displayed in order to give the user some direction. In this case, the title of the article provides sufficient context:
title: this.props.title
The second argument the showActionSheetWithOptions method takes is a callback function invoked when the user presses a button on the action sheet. The callback receives one argument, the index of the button that was selected. Since we have not yet created the ability to bookmark articles, we'll just log the selected index to the console:
(buttonIndex) => console.log('Button selected', buttonIndex) The ActionSheetIOS API comes with another method,
showShareActionSheetWithOptions, which can be used to show the native sharing menu of iOS. This allows users to share content from within an app to social media platforms, such as Facebook or Twitter, to printers, text message, and much more.
Alert
The Alert API is a cross-platform API used to create a pop-up alert dialog. An alert's function is to bring the user's attention to something urgent. Since we have yet to
implement the Bookmark tab of our application, let's use an alert to let the user know we are working hard to get this feature finished:
To implement this, we'll need to import the Alert API into our HomeScreen component: import {
TabBarIOS, Alert
} from 'react-native';
Next, we'll create a method within the HomeScreen component that will eventually be responsible for opening the alert:
showBookmarkAlert() { // Show alert here }
Finally, we'll call the showBookmarkAlert method when the bookmarks tab is selected, instead of navigating to that tab:
<TabBarIOS.Item systemIcon={'bookmarks'} selected={this.state.tab === 'bookmarks'} onPress={() => this.showBookmarkAlert()} > <Text>Bookmarks</Text> </TabBarIOS.Item>
Now that we have the setup out of the way, we must implement the showBookmarkAlert method and use the Alert API, as shown in the following code snippet:
showBookmarkAlert() { Alert.alert(
'Coming Soon!',
'We're hard at work on this feature, check back in the near future.', [
{ text: 'OK', onPress: () => console.log('User pressed OK') } ]
); }
The first argument that Alert.alert takes is the string title of the alert. The second is a string message, which is displayed below the title in a slightly smaller font size. The third argument is an array of objects that represent the buttons shown at the bottom of the alert. Each button has a text value that is displayed on the button and an onPress value, which is a function called when the user selects the button. Since we aren't responding to the press in any way, we'll simply log to the console.
Vibration
If the alert wasn't enough to get the user's attention, React Native also allows us to access the hardware and make the mobile device vibrate by using the Vibration API. This is a very simple API and can be implemented in only a few lines of code. We'll use it to give the user a jolt at the same time we show the alert from the previous section.
The first thing we need to do is add the Vibration API to the import statement of HomeScreen: import { TabBarIOS, Alert, Vibration } from 'react-native';
Next, we'll simply call the API's vibrate method right before we open the alert: showBookmarkAlert() {
Vibration.vibrate(); Alert.alert(
'Coming Soon!',
'We're hard at work on this feature, check back in the near future.', [
{ text: 'OK', onPress: () => console.log('User pressed OK') } ]
); }
And that's all there is to it! Note that, since your computer cannot vibrate, this will have no effect when running in the emulator.
StatusBar
The StatusBar API allows us to modify the operating system status bar displayed at the top of the screen. We've styled our application to have a dark theme. Since the default color of the status bar is also dark, it will probably be hard for users to read. We'll use the
First, we'll import the StatusBar API: import { TabBarIOS, Text, Alert, Vibration, StatusBar } from 'react-native';
Then we'll simply call the setBarStyle method, passing it the name of the theme we would like to use:
// Set the status bar for iOS to light StatusBar.setBarStyle('light-content');
Now the status bar stands out on the screen, as shown in the following screenshot:
Summary
React Native, like React for the Web, comes bundled with many components and APIs that give us direct access to native interfaces and functionality. We can use these components and APIs in combination to make more complex components of our own and, eventually, an entire application.
We said this at the beginning of the chapter, but it bears repeating, this list of components, props, and APIs is by no means comprehensive. Some of the components and APIs that were left out will be introduced in later chapters, though some will not. To find a comprehensive list, refer to the React Native documentation.
Before we take our RNNYT application to the next level, we'll first spend the next chapter discussing data management strategies for React applications.