React Native offers developers the ability to build mobile applications using the same technologies used for web development. It allows developers to create cross-platform mobile apps while reusing as much code as possible, reducing development time and effort. In this tutorial, we’ll walk through the basics of getting started with React Native and building a simple mobile application.
Prerequisites
Before we begin, we’ll need to make sure that we have a few things set up and ready to go. These include:
- Node.js and npm installed on your machine โ React Native is built on top of Node.js, which means that we’ll need to have it installed in order to use it. We can download Node.js and npm from the official Node.js website.
-
An IDE or text editor โ This can be any text editor or IDE of your choice, though we recommend using Visual Studio Code or Atom.
-
A mobile device or emulator โ We’ll need to have a mobile device or emulator set up in order to run our application. We recommend using either an Android emulator or the iOS Simulator that comes with Xcode.
Getting Started
Let’s start by creating a new React Native project. Open up your terminal and navigate to the directory where you want to create your project. Then, type the following command to initialize a new React Native project:
npx react-native init MyProject
This will create a new React Native project named MyProject
in the directory that you’re currently in. Once the project has been created, navigate into the newly created directory by typing:
cd MyProject
Next, we’ll need to start up the React Native development server. In your terminal, run the following command:
npx react-native start
This will start up the development server and open up a Metro Bundler page in your browser. The Metro Bundler page displays a list of all the JavaScript modules that have been loaded into your application, as well as any errors that may have occurred during the build process.
Now that the development server is up and running, we can start our mobile application. Open up a new terminal window and navigate to the root directory of your React Native project. Then, run the following command:
npx react-native run-ios
This command will start up the iOS Simulator and install your application on it. If you prefer to use an Android emulator instead, simply run the command npx react-native run-android
instead.
Congratulations! You’ve just run your first React Native application. The default React Native project will open in the mobile emulator or device.
Exploring the Code
Now that we have a basic application up and running, let’s take a look at the basic structure of a React Native project.
App.js
The App.js
file is the backbone of any React Native project. It’s where you’ll find the root component of your application, which is responsible for rendering all of the other components within your app. By default, the App.js
file contains a simple “Hello, world!” message.
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default function App() {
return (
<View style={styles.container}>
<Text>Hello, world!</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
index.js
The index.js
file is the entry point for your React Native application. It’s responsible for registering the root component of your application and rendering it to the mobile device or emulator.
import { AppRegistry } from 'react-native';
import App from './App';
import { name as appName } from './app.json';
AppRegistry.registerComponent(appName, () => App);
package.json
The package.json
file contains information about your React Native project, including the name, version, and dependencies. You can view and manage your dependencies by running npm install
in your project directory.
{
"name": "MyProject",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest"
},
"dependencies": {
"@react-native-community/masked-view": "^0.1.10",
"@react-navigation/native": "^5.7.3",
"@react-navigation/stack": "^5.9.0",
"react": "16.13.1",
"react-native": "0.63.2",
"react-native-gesture-handler": "^1.8.0",
"react-native-reanimated": "^1.13.0",
"react-native-safe-area-context": "^3.1.8",
"react-native-screens": "^2.10.1"
},
"devDependencies": {
"@babel/core": "^7.11.6",
"@babel/runtime": "^7.11.2",
"@react-native-community/eslint-config": "^1.1.0",
"babel-jest": "^26.3.0",
"eslint": "^7.10.0",
"jest": "^26.4.2",
"metro-react-native-babel-preset": "^0.63.0",
"react-test-renderer": "16.13.1"
},
"jest": {
"preset": "react-native"
}
}
Building a Basic User Interface
Now that we have a basic understanding of React Native and how to set up a new project, let’s build a simple user interface. For this tutorial, we’ll create a simple shopping list application that allows users to add items to their list.
Creating a New Component
To get started, let’s create a new component that will display our shopping list. Create a new file called ShoppingList.js
in your src
directory and add the following code:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default function ShoppingList() {
return (
<View style={styles.container}>
<Text style={styles.title}>Shopping List</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 40,
paddingHorizontal: 20,
backgroundColor: '#fff',
},
title: {
fontSize: 32,
fontWeight: 'bold',
marginBottom: 20,
},
});
The ShoppingList
component is a simple functional component that returns a View
component containing a Text
component displaying the title of our shopping list. It also includes some basic styles to set the background color, font size, and spacing.
Using the Component in App.js
Now that we have our ShoppingList
component, let’s use it in our App.js
file. Modify the App
function to look like this:
export default function App() {
return (
<View style={styles.container}>
<ShoppingList />
</View>
);
}
This will render the ShoppingList
component within our View
container.
Adding a Form to Add Items
Now that we have the basic structure of our shopping list, let’s add a form that will allow us to add new items. Create a new file called AddItem.js
in your src
directory and add the following code:
import React, { useState } from 'react';
import { StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { AntDesign } from '@expo/vector-icons';
export default function AddItem({ addItem }) {
const [text, setText] = useState('');
const handleChange = (value) => {
setText(value);
};
const handleSubmit = () => {
addItem(text);
setText('');
};
return (
<View style={styles.container}>
<TextInput
style={styles.input}
placeholder="Add Item..."
value={text}
onChangeText={handleChange}
/>
<TouchableOpacity style={styles.buttonContainer} onPress={handleSubmit}>
<AntDesign name="plus" size={24} color="white" />
<Text style={styles.buttonText}>Add</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
justifyContent: 'space-between',
alignContent: 'center',
marginHorizontal: 20,
marginVertical: 10,
},
input: {
height: 40,
borderColor: '#ccc',
borderWidth: 1,
borderRadius: 5,
paddingHorizontal: 10,
marginRight: 5,
flex: 1,
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#000',
borderRadius: 5,
paddingHorizontal: 10,
},
buttonText: {
color: '#fff',
marginLeft: 5,
fontSize: 16,
},
});
The AddItem
component is a functional component that takes in a prop called addItem
. This prop is a function that will be called when the user adds a new item to the shopping list.
The component contains a TextInput
component and a TouchableOpacity
component. The TextInput
component allows users to input the name of the item they want to add, and the TouchableOpacity
component is a button that they can press to add the item to the list.
Using the AddItem Component in ShoppingList.js
Now that we have our AddItem
component, let’s use it in our ShoppingList
component. Add the following code to the bottom of the ShoppingList
function:
const handleAddItem = (text) => {
console.log(text);
};
return (
<View style={styles.container}>
<Text style={styles.title}>Shopping List</Text>
<AddItem addItem={handleAddItem} />
</View>
);
This will display the AddItem
component below the title of our shopping list. The handleAddItem
function simply logs the text that’s passed in to the console for now, but we’ll update it later to actually add the item to our list.
Managing State to Update the UI
Now that we have our basic application structure in place, let’s focus on managing state in order to update our UI as the user interacts with it.
Updating handleAddItem to Change State
Currently, our handleAddItem
function simply logs the text that’s passed in to the console. Let’s update it to actually add the item to our list.
const [items, setItems] = useState([]);
const handleAddItem = (text) => {
setItems((prevItems) => [
...prevItems,
{ id: Math.random().toString(), text },
]);
};
This creates a new state variable called items
that’s an empty array by default. The handleAddItem
function takes in the text
value that’s passed in from the AddItem
component and adds a new item to the items
array. The new item is an object with an id
property (which is a randomly generated string) and a text
property (which contains the value of the text
variable).
Displaying the List of Items
Now that we’re adding items to our list, we need to display them in our UI. We can do this by mapping over the items
array and rendering a Text
component for each one.
<View style={styles.container}>
<Text style={styles.title}>Shopping List</Text>
<AddItem addItem={handleAddItem} />
{items.map((item) => (
<Text key={item.id}>{item.text}</Text>
))}
</View>
This will render each item in our items
array as a Text
component with the text
value of the item.
Adding the ability to delete items
Now that we have the ability to display our list of items, let’s add the ability to delete items when the user is done with them. We can do this by adding a delete button to each item that will remove it from the items
array.
<View style={styles.container}>
<Text style={styles.title}>Shopping List</Text>
<AddItem addItem={handleAddItem} />
{items.map((item) => (
<View key={item.id} style={styles.item}>
<Text style={styles.itemText}>{item.text}</Text>
<TouchableOpacity
style={styles.deleteButton}
onPress={() =>
setItems((prevItems) =>
prevItems.filter((prevItem) => prevItem.id !== item.id)
)
}
>
<Text style={styles.deleteButtonText}>Delete</Text>
</TouchableOpacity>
</View>
))}
</View>
This code adds a new property to each item object called id
. We also render each item as a new component called Item
, which contains the Text
component displaying the text
value of the item as well as a TouchableOpacity
component that triggers the setItems
function with a new array of items that excludes the item with the ID that matches the current item’s ID.
Final Code
Here’s the completed code for our simple shopping list application:
import React, { useState } from 'react';
import { StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { AntDesign } from '@expo/vector-icons';
export default function App() {
const [items, setItems] = useState([]);
const handleAddItem = (text) => {
setItems((prevItems) => [
...prevItems,
{ id: Math.random().toString(), text },
]);
};
return (
<View style={styles.container}>
<Text style={styles.title}>Shopping List</Text>
<AddItem addItem={handleAddItem} />
{items.map((item) => (
<View key={item.id} style={styles.item}>
<Text style={styles.itemText}>{item.text}</Text>
<TouchableOpacity
style={styles.deleteButton}
onPress={() =>
setItems((prevItems) =>
prevItems.filter((prevItem) => prevItem.id !== item.id)
)
}
>
<Text style={styles.deleteButtonText}>Delete</Text>
</TouchableOpacity>
</View>
))}
</View>
);
}
function AddItem({ addItem }) {
const [text, setText] = useState('');
const handleChange = (value) => {
setText(value);
};
const handleSubmit = () => {
addItem(text);
setText('');
};
return (
<View style={styles.container}>
<TextInput
style={styles.input}
placeholder="Add Item..."
value={text}
onChangeText={handleChange}
/>
<TouchableOpacity style={styles.buttonContainer} onPress={handleSubmit}>
<AntDesign name="plus" size={24} color="white" />
<Text style={styles.buttonText}>Add</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 40,
paddingHorizontal: 20,
backgroundColor: '#fff',
},
title: {
fontSize: 32,
fontWeight: 'bold',
marginBottom: 20,
},
item: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
borderColor: '#ccc',
borderWidth: 1,
borderRadius: 5,
paddingHorizontal: 10,
paddingVertical: 10,
marginVertical: 5,
},
itemText: {
fontSize: 18,
},
deleteButton: {
backgroundColor: '#ff0000',
borderRadius: 5,
paddingHorizontal: 10,
paddingVertical: 5,
},
deleteButtonText: {
color: '#fff',
},
input: {
height: 40,
borderColor: '#ccc',
borderWidth: 1,
borderRadius: 5,
paddingHorizontal: 10,
marginRight: 5,
flex: 1,
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#000',
borderRadius: 5,
paddingHorizontal: 10,
},
buttonText: {
color: '#fff',
marginLeft: 5,
fontSize: 16,
},
});
Conclusion
In this tutorial, we covered the basics of getting started with React Native, including setting up a new project, creating components, managing state, and updating the UI. By following this tutorial, you should now have a better understanding of how to build mobile applications using React Native. With this knowledge, you can continue to build more complex applications and explore the vast array of libraries and tools available for React Native development.