11.2 The same but different

# User Input

# Form Elements

There is no <form /> container element. This is an HTML convention used to bundle form data for submission to the server. To organize the layout of your input elements, you can use a standard View (opens new window) component, or a ScrollView (opens new window) component if your form is really long.

# TextInput

Use the TextInput (opens new window) component to collect free form text input from the user. This should be a controlled component with a state variable to hold the input value. There is a onChange event to give you full flexibility in your event handler, but there is also a simpler onChangeText event with a simpler API - see example below.











 





 









import React from 'react';
import { View, TextInput } from 'react-native';

const DemoTextInput = () => {
  const [firstName, setFirstName] = React.useState('');
  const [lastName, setLastName] = React.useState('');

  return (
    <View style={{ flex: 1 }}>
      <TextInput
        style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
        onChangeText={(text) => setFirstName(text)}
        value={firstName}
      />

      <TextInput
        style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
        onChange={(event) => setLastName(event.nativeEvent.text)}
        value={lastName}
      />
    </View>
  );
};

export default DemoTextInput;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# Switch

For binary inputs, the HTML checkbox is replace with the Switch (opens new window) component. Like the TextInput, this is a controlled component and there is a convenience event for handling input changes called onValueChange.





 



<Switch
  trackColor={{ false: '#767577', true: '#81b0ff' }}
  thumbColor={isEnabled ? '#f5dd4b' : '#f4f3f4'}
  ios_backgroundColor="#3e3e3e"
  onValueChange={(value) => setIsEnabled(value)}
  value={isEnabled}
/>
1
2
3
4
5
6
7

Also, notice there are special props for setting the color of the various visual elements of the <Switch /> component, and you would normally want to conditionally change those colours based on the value (true | false). The behaviour is slightly different between iOS and Android. Check the docs for these props.

# Picker

In place of the familiar HTML <select> list. React Native has the Picker (opens new window) component. This component is a community developed component and must be explicitly added to your project.

expo install @react-native-community/picker
1

Don't forget to import it in your application.

import { Picker } from '@react-native-community/picker';
1

Suppose we want to ask the user what their favourite programming language is. You will need a state variable language for the controlled component, and then in your JSX ...

<Picker
  selectedValue={language}
  style={{ height: 50, width: 100 }}
  itemStyle={{ color: 'white' }}
  onValueChange={(itemValue, itemIndex) => setLanguage(itemValue)}
>
  <Picker.Item label="JavaScript" value="js" />
  <Picker.Item label="Swift" value="swift" />
  <Picker.Item label="Kotlin" value="kotlin" />
  <Picker.Item label="Java" value="java" />
</Picker>
1
2
3
4
5
6
7
8
9
10
11

# SegmentedControl

Where is the good old radio button? Oh right, no HTML. Instead we have the native UI SegmentedControl (opens new window). This is also a community developed component.

expo install @react-native-community/segmented-control
1

Don't forget to import it in your application.

import SegmentedControl from '@react-native-community/segmented-control';
1

Then in your JSX ...

const [languageIndex, setLanguageIndex] = React.useState(1);

return (
  <SegmentedControl
    values={['JavaScript', 'Swift', 'Kotlin']}
    selectedIndex={languageIndex}
    onChange={(event) =>
      setLanguageIndex(event.nativeEvent.selectedSegmentIndex)
    }
  />
);
1
2
3
4
5
6
7
8
9
10
11

# Images

For displaying images import the Image (opens new window) component from react-native.

To choose and image from the camera roll, you need the ImagePicker (opens new window) component from Expo.

# Lists

List Reference (opens new window)

One thing to keep in mind with <FlatList> in React Native, you will be using it for most times when you would have used myArray.map() in ReactJS.

# FlatList

Got a lot of elements to render? Want to lazy load them? Need to be able to scroll to see the new children as they are rendered? FlatList is what you need.

To use a FlatList, it needs to be imported from react-native, it needs an Array of data to be used as the source for the items, it needs a Component to render for each Item in the Array, and it needs a method to extract a value from the Array Item that will be used as the key to be used for each Component.

import React from 'react';
import { SafeAreaView } from 'react-native-safe-area-context';
import { View, FlatList, Text } from 'react-native';
//the data to be used in the items.
const DATA = [
  {
    id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
    title: 'First Item',
  },
  {
    id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
    title: 'Second Item',
  },
  {
    id: '58694a0f-3da1-471f-bd96-145571e29d72',
    title: 'Third Item',
  },
];
//the component to render for each data item
const Item = ({ title }) => (
  <View>
    <Text>{title}</Text>
  </View>
);
//the screen that will render the list
const App = () => {
  return (
    <SafeAreaView>
      <FlatList
        data={DATA}
        renderItem={Item}
        keyExtractor={(item) => {
          return item.id;
          //OR your data can have a `key` property
        }}
        ListEmptyComponent={<Spinner />}
        onEndReached={() => {
          //function that runs when the end of the list is rendered
        }}
        numColumns={2}
        extraData={extraInfoLikeSelectedItemID}
        ListHeaderComponent={<Text>TOP</Text>}
        ListFooterComponent={<Text>Bottom</Text>}
      />
    </SafeAreaView>
  );
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# SectionList

A SectionList is FlatList that has headings for categories of elements within the list. Think of a list of contacts that are divided by the first letter of the last name.

It works the same way as the FlatList except it has an extra property renderSectionHeader.

const DATA = [
  { title: 'heading one', data: ['a', 'b', 'c'] },
  { title: 'heading two', data: ['a', 'b'] },
  { title: 'heading three', data: ['a', 'b', 'c', 'd', 'e'] },
];
//needs an array of objects
//each object has a title property and a data array.
//the data array are the items like FlatList
<SectionList
  sections={DATA}
  keyExtractor={(item, index) => item + index}
  renderItem={({ item }) => <Item title={item} />}
  renderSectionHeader={({ section: { title } }) => (
    <Text style={styles.header}>{title}</Text>
  )}
/>;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# ScrollView

The biggest difference between a FlatList and a ScrollView is that the ScrollView renders ALL of its children at once. This comes with performance penalties.

ScrollView reference (opens new window)

Here is an example of a ScrollView wrapped around the Text element.

import React from 'react';
import { SafeAreaView } from 'react-native-safe-area-context';
import { StyleSheet, Text, ScrollView, StatusBar } from 'react-native';

const App = () => {
  return (
    <SafeAreaView style={styles.container}>
      <ScrollView style={styles.scrollView}>
        <Text style={styles.text}>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
        </Text>
      </ScrollView>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: StatusBar.currentHeight,
  },
  scrollView: {
    paddingHorizontal: 20,
  },
  text: {
    fontSize: 48,
  },
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Last Updated: : 12/1/2021, 12:26:41 PM