Getting Started with React Native
Why React Native
React Native is is a framework that enables you to build cross-platform mobile applications using React and JavaScript. It enables you to use the same components on iOS and Android platforms. The UI components can also be customized for each platform.
What we will be building
This guide would walk you through building a to-do application in React Native with features like:
- Adding a new to-do item.
- Deleting a to-do item.
- Marking a to-do item as done and undone.
Before you begin
Follow the instructions here to set up your React Native development environment for your development OS (macOS, Windows, or Linux) and target OS (iOS or Android).
Tools used.
- React Native: This will be used to build our mobile application (iOS or Android) in JavaScript.
- React Native Vector Icons: This contains icons that will be used in our React Native mobile application.
Project setup.
Navigate to a specific directory on your machine and run the following commands to generate a new React Native project.
react-native init todo
Navigate to the project directory and start your React Native application by running the following command. Ensure you have your virtual device or emulator running.
cd todo
react-native run-android
If all things worked properly, you should have a screen like this displayed on your Android emulator or device.
Create the src
directory containing the components
and styles
subfolder.
The components folder will contain all of our React components while the styles folder will contain all of our stylings for the components.
mkdir -p src/{components,styles}
Adding new to-do items
Create a todoStyles.js
file in the src/styles
directory. This will contain all of the styles for our Todo
component that we will create later. Add the code below to the file.
src/styles/todoStyles.js
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
padding: 10,
backgroundColor: 'white'
},
inputContainer: {
height: 50
},
separator: {
borderBottomColor: '#d1d0d4',
borderBottomWidth: 1
}
});
export default styles;
Create a todo.js
file in the src/components
directory and add the code below to the file.
src/components/todo.js
import React, { Component } from 'react';
import { TextInput, View } from 'react-native';
import styles from '../styles/todoStyles';
class Todo extends Component {
constructor(props) {
super(props);
this.state = {
text: '',
todos: []
};
}
onSubmit = () => {
if (this.state.text) {
this.setState(prevState => ({
text: '',
todos: [...prevState.todos,
{ title: prevState.text, done: false }]
}));
this.textInput.setNativeProps({ text: '' });
}
}
render () {
return (
<View style={styles.container} >
<TextInput
selectionColor="black"
underlineColorAndroid="black"
placeholder="What needs to be done"
onChangeText={text => this.setState({ text })}
onSubmitEditing={this.onSubmit}
ref={(component) => { this.textInput = component; }}
autoFocus
/>
</View>
)
}
}
export default Todo;
The todo.js
file will contain most of our application code. The View
React Native component acts as the container for other child components.
The TextInput
is a component that enables a user to enter text. The onChangeText
prop on the TextInput
takes a function that is called each time the text changes. this.setState({ text })
is called in the anonymous function passed to the onChangeText
prop to change the value of the text
property in the state
of the todo component.
The onSubmitEditing
prop on the TextInput
takes a function that is called each time the text is submitted. The onSubmit
method in the todo class adds a new to-do item to the todos array in the state and changes the text property in the state to an empty string. An update function is passed to this.setState
here because the update/new value of state depends on the current value. It enables us to always access the most updated version of the state.
A ref
was added to the text input to enable us to use setNativeProps
props to clear the input every time it is submitted. A ref
enables us to directly manipulate elements.
Replace the contents of the App.js
file in the root
directory with the code below. This imports our Todo
components and renders it as a child of the App
component.
App.js
import React from 'react';
import {
StyleSheet,
Text,
View
} from 'react-native';
import Todo from './src/components/todo';
const App = () =>
(
<View style={styles.container}>
<Text style={styles.welcome}>
React Native Todo App
</Text>
<Todo/>
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
export default App;
Displaying our to-do items
Create a todoItemStyles.js
file in the src/styles
directory. This file will contain all of the styles for our TodoItem
component which we will create later. Add the code below to the todoItemStyles.js
file.
src/styles/todoItemStyles.js
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
container: { flex: 1, flexDirection: 'row' },
text: {
flex: 1,
marginHorizontal: 10,
textAlignVertical: 'center',
fontSize: 18
}
});
export default styles;
Create a todoItem.js
file in the src/components
directory. This file will contain the component that would display our to-do items. Add the code below to the file.
src/components/todoItem.js
import React from 'react';
import { Text, View, TouchableHighlight } from 'react-native';
import styles from '../styles/todoItemStyles';
const TodoItem = ({item}) =>
(
<View style={styles.container} >
<Text style={styles.text}
>{item.title}
</Text>
</View>
);
export default TodoItem;
Import our TodoItem
component in src/components/todo.js
. Import the FlatList React Native element too.
...
import { TextInput, View, FlatList } from 'react-native';
import TodoItem from '../components/todoItem'
...
Add the FlatList
React Native component to the return value of the render method in the Todo class in src/components/todo.js
. The Flatlist react-native element would be used to display our list of to-dos.
...
<FlatList
ItemSeparatorComponent={this.separator}
data={this.state.todos}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
/>
...
Add the methods below to the Todo
class in src/components/todo.js
.
...
keyExtractor = (item, index) => index;
separator = () => <View style={styles.separator} />;
renderItem = ({ item, index }) => (
<TodoItem
item={item}
index={index}
markAsDone={this.markAsDone}
onPressRemove={this.onPressRemove}
/>
);
...
The renderItem
method returns our TodoItem
component that is rendered for each item in the todos
array in our Todo
component's state. The separator
method returns a component that is used to separate each item in the FlatList
. The key extractor
tells the FlatList
view to use the index of the item as unique identifiers of each item in the view.
Updated src/components/Todo.js
import React, { Component } from 'react';
import { TextInput, View, FlatList } from 'react-native';
import TodoItem from '../components/todoItem';
import styles from '../styles/todoStyles';
class Todo extends Component {
constructor(props) {
super(props);
this.state = {
text: '',
todos: [{ title: 'test', done: false }]
};
}
onSubmit = () => {
if (this.state.text) {
this.setState(prevState => ({
text: '',
todos: [...prevState.todos,
{ title: prevState.text, done: false }]
}));
this.textInput.setNativeProps({ text: '' });
}
}
keyExtractor = (item, index) => index;
separator = () => <View style={styles.separator} />;
renderItem = ({ item, index }) => (
<TodoItem
item={item}
index={index}
/>
);
render() {
return (
<View style={styles.container} >
<TextInput
selectionColor="black"
underlineColorAndroid="black"
placeholder="What needs to be done"
onChangeText={text => this.setState({ text })}
onSubmitEditing={this.onSubmit}
ref={(component) => { this.textInput = component; }}
autoFocus
/>
<FlatList
ItemSeparatorComponent={this.separator}
data={this.state.todos}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
/>
</View>
);
}
}
export default Todo;
Our to-do items should now be visible after they are submitted in the TextInput
.
Our app on the Android emulator should now look like this.
Deleting todo items
Run the following command to install react-native-vector-icons and link it to our application.
npm install --save react-native-vector-icons
npm install
react-native link
We will need to restart our application after this.
react-native run-android
Add the method below to the Todo
class insrc/components/todo.js
. This method will handle the removal of to-do items from the todos array in our components state. It filters out the array item with the index passed it as an argument from the todos array in the state.
...
onPressRemove = (index) => {
this.setState(prevState => ({
todos: prevState.todos.filter((_, i) => i !== index)
}));
}
...
Update renderItem
method in the todo class to include the onpressRemove
property on the TodoItem
component.
...
renderItem = ({ item, index }) => (
<TodoItem
item={item}
index={index}
onPressRemove={this.onPressRemove}
/>
);
...
Update our todoItem.js
file with the code below.
import React from 'react';
import { Text, View, TouchableHighlight } from 'react-native';
import styles from '../styles/todoItemStyles';
import Icon from 'react-native-vector-icons/FontAwesome';
const TodoItem = ({item, index , onPressRemove}) =>
(
<View style={styles.container} >
<Text style={styles.text}
>{item.title}
</Text>
<TouchableHighlight
onPress={() => onPressRemove(index)}
>
<Icon name="remove" size={30} color="#d75452" />
</TouchableHighlight>
</View>
);
export default TodoItem;
The TouchableHighlight
is a React Native element that enables us to handle touches. The TouchableHighlight
React Native element onPress
prop takes a function that is called each time it is pressed. The Icon
from React-Native-vector-Icons enables use of hundreds of customizable icons in our application.
Save all changes and reload the application. Our application should now look like this. Clicking the remove
icon should remove the to-do item.
Marking to-do items as done
Add the method below to the Todo
class in src/components/todo.js
. This method will change the value of done
key of a to-do Item object with a particular index to true or false and update our component's state.
...
markAsDone = (index) => {
this.setState(prevState => ({
todos: prevState.todos.map((item, i) => {
if (i === index) {
item.done = !item.done;
return item;
}
return item;
})
}));
}
...
Update the renderItem
method in the Todo
class in src/components/todo.js
to pass the prop markAsDone
to the TodoItem
component.
...
renderItem = ({ item, index }) => (
<TodoItem
item={item}
index={index}
markAsDone={this.markAsDone}
onPressRemove={this.onPressRemove}
/>
);
...
Update the todoItem.js
with the code below.
src/components/todoItem.js
import React from 'react';
import { Text, View, TouchableHighlight } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import styles from '../styles/todoItemStyles';
const TodoItem = ({
item, index, onPressRemove, markAsDone
}) =>
(
<View style={styles.container} >
<TouchableHighlight
onPress={() => markAsDone(index)}
underlayColor="white"
>
{ item.done ?
<Icon name="check-square-o" size={30} color="#5fb660" /> :
<Icon name="square-o" size={30} color="#808080" />
}
</TouchableHighlight>
<Text style={[
styles.text, {
textDecorationLine: item.done ? 'line-through' : 'none',
color: item.done ? '#808080' : 'black'
}]}
>{item.title}
</Text>
<TouchableHighlight
onPress={() => onPressRemove(index)}
>
<Icon name="remove" size={30} color="#d75452" />
</TouchableHighlight>
</View>
);
export default TodoItem;
A second TouchableHighlight
is added here, which is used to mark a to-do item as done.
There is conditional rendering being used in this component. It renders the check-square-o
Icon when the to-do item is marked as done and renders the square-o
icon when the to-do item is marked as undone.
The text-decoration and color style property of the todoItem
text is also changed based on the status of the done property of the to-do item. When the to-do item is done, the text color is gray and the text-decoration is lined-through, otherwise the text-decoration is none and the text color is black.
Clicking the square-o
Icon should mark a to-do item as done and vice versa.
Once done, our final application should look like this.
Conclusion
Our application is now complete! If you have any questions or comments, please add them to the comments section below.
The complete application source code can be viewed here.
hello,
i am an android developer. Now i want to learn react native.
i installed node.js and npm etc. project running successfully but not showing desired output. its showing just “unable to load script from assets ‘index.android.bundle’.” please help me.
Are you developing on Windows or Mac OS?
What version of react-native are you using?
Have you tried using a new android virtual device or wiping the data from the android virtual device you currently use and restarting it from you AVD manager?
m using the window 7 (32 bit).
tried with emulator and physical device also.
but getting same error on both case.
can u please share the contact (mobile) number for fast communication.