2.1 Forms, Images, Lists
# User Input
You can find the list of common basic React Native UI components here. This is seems very short though.
Expo has a long list of components that we get to use as part of our project too, because we used Expo to create our React Native project. If you go to the Expo Reference section you will see a much longer list of components and apis in the left hand menu.
It is important to note however, that many of the Expo components and apis will need to you install that component in your project first.
# 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 component, or a ScrollView component if your form is really long.
# TextInput
Use the TextInput 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;
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 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}
/>
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 component. This component is a community developed component and must be
explicitly added to your project.
npx expo install @react-native-community/picker
Don't forget to import it in your application.
import { Picker } from '@react-native-community/picker';
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>
2
3
4
5
6
# SegmentedControl
Where is the good old radio button? Oh right, no HTML. Instead we have the native UI SegmentedControl. This is also a community developed component.
npx expo install @react-native-community/segmented-control
Don't forget to import it in your application.
import SegmentedControl from '@react-native-community/segmented-control';
Then in your JSX ...
const [languageIndex, setLanguageIndex] = React.useState(1);
return <SegmentedControl values={['JavaScript', 'Dart', 'Swift', 'Kotlin']} selectedIndex={languageIndex} onChange={(event) => setLanguageIndex(event.nativeEvent.selectedSegmentIndex)} />;
2
3
# Buttons
There is a Button control in the React Native built-in component list.
Nothing really unexpected with this control. It does use an onPress
attribute instead of an onClick
like React though.
<Button onPress={onPressFunc} title="Learn More" color="#841584" accessibilityLabel="Learn more about this purple button" />
# Images
For displaying images import the Image component from react-native
.
If you want to add an image to any screen in a React Native app we use the <Image>
component with a source
attribute. The source
attribute will use a require()
method to load the image using a
relative path for a local image.
<Image source={require('./myimage.jpg')} />
For images included via Xcode asset catalogs or in the Android drawable folder, use the image name without the extension:
<Image source={{ uri: 'app_icon' }} style={{ width: 40, height: 40 }} />
For images in the Android assets folder, use the asset:/
scheme:
<Image source={{ uri: 'asset:/app_icon.png' }} style={{ width: 40, height: 40 }} />
If you need to load an image from a remote URL you will also use an object with a uri
property that has the URL as the value.
<Image source={{ uri: 'https://reactjs.org/logo-og.png' }} style={{ width: 400, height: 400 }} />
For more details and variations on loading images and other assets, see the Image component reference.
To choose and image from the camera roll, you need the ImagePicker component from Expo.
# Lists
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}
ListHeaderComponent={<Text>TOP</Text>}
ListFooterComponent={<Text>Bottom</Text>}
/>
</SafeAreaView>
);
};
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
# 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>}
/>;
2
3
4
5
6
7
8
9
10
11
12
13
14
# 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.
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,
},
});
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
# What to do this week
TODO Things to do before next week.
- Read all the content from
Modules 2.1, 2.2, and 3.1
. - Spend some time with the Hybrid modules and assignments about Dart.
- Start watching the React Native Playlist