Chapter 19. Collecting User Input

In web applications, it's easy to collect user input because standard HTML form elements look and behave similar on all browsers. With native UI platforms, collecting user input is a little more nuanced.

In this chapter, you'll learn how to work with the various React Native components that are used to collect user input. These include text input, selecting from a list of options, checkboxes, and date/time selectors. You'll see the differences between iOS and Android, and how to implement the appropriate abstractions for your app.

Collecting text input

Collecting text input seems like something that should be super easy to implement, even in React Native. It's easy, but there's a lot to think about when implementing text inputs. For example, should it have placeholder text? Is this sensitive data that shouldn't be displayed on screen? Should we process text as it's entered, or when the user moves to another field? The list goes on, and I only have so much room in this book.

What's markedly different about mobile text input versus traditional web text input is that the former has its own built-in virtual keyboard that we can configure and respond to. So without further delay, let's get coding. We'll render several instances of the <TextInput> component:

import React, { Component, PropTypes } from 'react'; 
import { 
  AppRegistry, 
  Text, 
  TextInput, 
  View, 
} from 'react-native'; 
import { fromJS } from 'immutable'; 
 
import styles from './styles'; 
 
// A Generic "<Input>" component that we can use in our app. 
// It's job is to wrap the "<TextInput>" component in a "<View>" 
// so that we can render a label, and to apply styles to the 
// appropriate components. 
const Input = props => ( 
  <View style={styles.textInputContainer}> 
    <Text style={styles.textInputLabel}> 
      {props.label} 
    </Text> 
    <TextInput 
      style={styles.textInput} 
      {...props} 
    /> 
  </View> 
); 
 
Input.propTypes = { 
  label: PropTypes.string, 
}; 
 
class CollectingTextInput extends Component { 
  // This state is only relevant for the "input events" 
  // component. The "changedText" state is updated as 
  // the user types while the "submittedText" state is 
  // updated when they're done. 
  state = { 
   data: fromJS({ 
      changedText: '', 
      submittedText: '', 
    }), 
  } 
 
  // Getter for "Immutable.js" state data... 
  get data() { 
    return this.state.data; 
  } 
 
  // Setter for "Immutable.js" state data... 
  set data(data) { 
    this.setState({ data }); 
  } 
 
  render() { 
    const { 
      changedText, 
      submittedText, 
    } = this.data.toJS(); 
 
    return ( 
      <View style={styles.container}> 
        {/* The simplest possible text input. */} 
        <Input 
          label="Basic Text Input:" 
        /> 
 
        { /* The "secureTextEntry" property turns 
             the text entry into a password input 
             field. */ } 
        <Input 
          label="Password Input:" 
          secureTextEntry 
        /> 
 
        { /* The "returnKeyType" property changes 
             the return key that's displayed on the 
             virtual keyboard. In this case, we want 
             a "search" button. */ } 
        <Input 
          label="Return Key:" 
          returnKeyType="search" 
        /> 
 
        { /* The "placeholder" property works just 
             like it does with web text inputs. */ } 
        <Input 
          label="Placeholder Text:" 
          placeholder="Search" 
        /> 
 
        { /* The "onChangeText" event is triggered as 
             the user enters text. The "onSubmitEditing" 
             event is triggered when they click "search". */ } 
        <Input 
          label="Input Events:" 
          onChangeText={(e) => { 
            this.data = this.data 
              .set('changedText', e); 
          }} 
          onSubmitEditing={(e) => { 
            this.data = this.data.set( 
              'submittedText', 
              e.nativeEvent.text 
            ); 
          }} 
          onFocus={() => { 
            this.data = this.data 
              .set('changedText', '') 
              .set('submittedText', ''); 
          }} 
        /> 
 
        { /* Displays the captured state from the 
             "input events" text input component. */ } 
        <Text>Changed: {changedText}</Text> 
        <Text>Submitted: {submittedText}</Text> 
      </View> 
    ); 
  } 
} 
 
AppRegistry.registerComponent( 
  'CollectingTextInput', 
  () => CollectingTextInput 
); 

I won't go into depth on what each of these <TextInput> components is doing—there are comments in the code. Let's see what these components look like on screen:

Collecting text input

As you can see, the plain text input just shows the text that's been entered. The password field doesn't reveal any characters. The placeholder text is displayed when the input is empty. The changed text state is also displayed. You're not seeing the submitted text state, because I didn't press the submit button on the virtual keyboard before I took the screenshot.

Let's take a look at the actual virtual keyboard for the input element where we changed the return key:

Collecting text input

When the keyboard return key reflects what's going to happen when they press it, the user feels more in tune with the application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset