How to Create ToDo App using React Native ?
In this article, we'll see how to create a To-Do app using React Native. An ideal illustration of a basic application that can be developed with React Native is a To-Do app. This app enables users to generate, modify, and remove tasks, assisting them in maintaining organization and concentration.

To give you a better idea of what we’re going to create, let’s watch a demo video.
Demo Video
Playground
Note: This Section is to interact with the app which you are going to build.
Prerequisites
- Introduction to React Native
- Introduction to React Native Components
- React Native State
- React Native Props
- React useState Hook
- Expo CLI
Step-by-Step Implementation
Step 1: Create a React Native Project
Now, create a project with the following command.
npx create-expo-app app-name --template
Note: Replace the app-name with your app name for example : react-native-demo-app
Next, you might be asked to choose a template. Select one based on your preference as shown in the image below. I am selecting the blank template because it will generate a minimal app, as clean as an empty canvas in JavaScript.

It completes the project creation and displays a message: "Your Project is ready!" as shown in the image below.

Now go into your project folder, i.e., react-native-demo
cd app-name
Project Structure:

Step 2: Run Application
Start the server by using the following command.
npx expo start
Then, the application will display a QR code.
- For the Android users,
- For the Android Emulator, press " a" as mentioned in the image below.
- For the Physical Device, download the " Expo Go " app from the Play Store. Open the app, and you will see a button labeled " Scan QR Code. " Click that button and scan the QR code; it will automatically build the Android app on your device.
- For iOS users, simply scan the QR code using the Camera app .
- If you're using a web browser, it will provide a local host link that you can use as mentioned in the image below.

Step 3: Start Coding
- Approach:
To develop a React Native todo application, it is crucial to adhere to a systematic method. Commence by specifying the features and functionalities of the app, encompassing tasks like adding, modifying, and removing items. Outline the architecture and data flow of the app, determining the required components and their interactions. Explore options for managing the app's state using React hooks or a state management library, and select a suitable data storage solution for preserving tasks. Design the user interface by breaking it down into reusable components, and incorporate navigation if necessary. Conduct comprehensive testing, including unit tests for critical functions and components, as well as user testing for obtaining feedback on usability.
- Import libraries:
Import required libraries at the top of the file.
import { useState } from "react"; // Importing useState hook from React
import {
View, // Importing View component for layout
Text, // Importing Text component for displaying text
TextInput, // Importing TextInput component for user input
TouchableOpacity, // Importing TouchableOpacity for button-like behavior
FlatList, // Importing FlatList for rendering lists
StyleSheet, // Importing StyleSheet for styling components
} from "react-native"; // Importing necessary components from React Native
- StyleSheet:
Create a StyleSheet to style components like container, title, heading, input, addButton, addButtonText, task, itemList, taskButton, editButton and deleteButton.
// Styles for the components
const styles = StyleSheet.create({
container: {
flex: 1, // Take full screen height
padding: 40, // Add padding around the container
marginTop: 40, // Add margin at the top
},
title: {
fontSize: 24, // Font size for the title
fontWeight: "bold", // Bold font
marginBottom: 20, // Margin below the title
},
heading: {
fontSize: 30, // Font size for the heading
fontWeight: "bold", // Bold font
marginBottom: 7, // Margin below the heading
color: "green", // Green color for the heading
},
input: {
borderWidth: 3, // Border width for the input field
borderColor: "#ccc", // Border color
padding: 10, // Padding inside the input field
marginBottom: 10, // Margin below the input field
borderRadius: 10, // Rounded corners
fontSize: 18, // Font size for the input text
},
addButton: {
backgroundColor: "green", // Background color for the button
padding: 10, // Padding inside the button
borderRadius: 5, // Rounded corners
marginBottom: 10, // Margin below the button
},
addButtonText: {
color: "white", // Text color
fontWeight: "bold", // Bold font
textAlign: "center", // Center align the text
fontSize: 18, // Font size for the button text
},
task: {
flexDirection: "row", // Arrange items in a row
justifyContent: "space-between", // Space between items
alignItems: "center", // Align items vertically in the center
marginBottom: 15, // Margin below each task
fontSize: 18, // Font size for the task text
},
itemList: {
fontSize: 19, // Font size for the task text
},
taskButtons: {
flexDirection: "row", // Arrange buttons in a row
},
editButton: {
marginRight: 10, // Margin to the right of the edit button
color: "green", // Green color for the edit button text
fontWeight: "bold", // Bold font
fontSize: 18, // Font size for the edit button text
},
deleteButton: {
color: "red", // Red color for the delete button text
fontWeight: "bold", // Bold font
fontSize: 18, // Font size for the delete button text
},
});
- Main UI:
Below is the code for the Main UI, which contains components like a
- TextInput : To take input from the user
- TouchableOpacity: Buttons for Add, Update, and Delete tasks
- Text: Used to display the text on the screen.
- FlatList : Used to display a list of tasks.
<View style={styles.container}>
<Text style={styles.heading}>Geeksforgeeks</Text> {/* App heading */}
<Text style={styles.title}>ToDo App</Text> {/* App title */}
<TextInput
style={styles.input}
placeholder="Enter task" // Placeholder text for the input field
value={task} // Bind input value to task state
onChangeText={(text) => setTask(text)} // Update task state on text change
/>
<TouchableOpacity
style={styles.addButton}
onPress={handleAddTask} // Call handleAddTask on button press
>
<Text style={styles.addButtonText}>
{editIndex !== -1 ? "Update Task" : "Add Task"} {/* Button text changes based on edit mode */}
</Text>
</TouchableOpacity>
<FlatList
data={tasks} // Pass tasks array as data
renderItem={renderItem} // Render each task using renderItem
keyExtractor={(_item, index) => index.toString()} // Unique key for each item
/>
</View>
- renderItem:
Function to render each task item.
const renderItem = ({ item, index }) => (
<View style={styles.task}>
<Text style={styles.itemList}>{item + " "}</Text> {/* Display the task */}
<View style={styles.taskButtons}>
<TouchableOpacity onPress={() => handleEditTask(index)}>
<Text style={styles.editButton}>Edit</Text> {/* Edit button */}
</TouchableOpacity>
<TouchableOpacity onPress={() => handleDeleteTask(index)}>
<Text style={styles.deleteButton}>Delete</Text> {/* Delete button */}
</TouchableOpacity>
</View>
</View>
);
- handleAddTask:
Function to handle adding or updating a task.
const handleAddTask = () => {
if (task) {
if (editIndex !== -1) {
// If editIndex is not -1, update the existing task
const updatedTasks = [...tasks];
updatedTasks[editIndex] = task; // Update the task at the specified index
setTasks(updatedTasks); // Update the tasks state
setEditIndex(-1); // Reset editIndex
} else {
// If editIndex is -1, add a new task
setTasks([...tasks, task]); // Add the new task to the tasks array
}
setTask(""); // Clear the input field
}
};
- handleEditTask:
Function to handle editing a task.
const handleEditTask = (index) => {
const taskToEdit = tasks[index]; // Get the task to be edited
setTask(taskToEdit); // Set the task in the input field
setEditIndex(index); // Set the index of the task being edited
};
- handleDeleteTask:
Function to handle deleting a task.
const handleDeleteTask = (index) => {
const updatedTasks = [...tasks];
updatedTasks.splice(index, 1); // Remove the task at the specified index
setTasks(updatedTasks); // Update the tasks state
};
- useState:
useState is used to manage the state of the task input, list of tasks, and index of the task being edited.
// State to store the current task input
const [task, setTask] = useState("");
// State to store the list of tasks
const [tasks, setTasks] = useState([]);
// State to track the index of the task being edited
const [editIndex, setEditIndex] = useState(-1);
Complete Source Code
App.js:
import { useState } from "react"; // Importing useState hook from React
import {
View, // Importing View component for layout
Text, // Importing Text component for displaying text
TextInput, // Importing TextInput component for user input
TouchableOpacity, // Importing TouchableOpacity for button-like behavior
FlatList, // Importing FlatList for rendering lists
StyleSheet, // Importing StyleSheet for styling components
} from "react-native"; // Importing necessary components from React Native
// Main App component
const App = () => {
// State to store the current task input
const [task, setTask] = useState("");
// State to store the list of tasks
const [tasks, setTasks] = useState([]);
// State to track the index of the task being edited
const [editIndex, setEditIndex] = useState(-1);
// Function to handle adding or updating a task
const handleAddTask = () => {
if (task) {
if (editIndex !== -1) {
// If editIndex is not -1, update the existing task
const updatedTasks = [...tasks];
updatedTasks[editIndex] = task; // Update the task at the specified index
setTasks(updatedTasks); // Update the tasks state
setEditIndex(-1); // Reset editIndex
} else {
// If editIndex is -1, add a new task
setTasks([...tasks, task]); // Add the new task to the tasks array
}
setTask(""); // Clear the input field
}
};
// Function to handle editing a task
const handleEditTask = (index) => {
const taskToEdit = tasks[index]; // Get the task to be edited
setTask(taskToEdit); // Set the task in the input field
setEditIndex(index); // Set the index of the task being edited
};
// Function to handle deleting a task
const handleDeleteTask = (index) => {
const updatedTasks = [...tasks];
updatedTasks.splice(index, 1); // Remove the task at the specified index
setTasks(updatedTasks); // Update the tasks state
};
// Function to render each task item
const renderItem = ({ item, index }) => (
<View style={styles.task}>
<Text style={styles.itemList}>{item + " "}</Text> {/* Display the task */}
<View style={styles.taskButtons}>
<TouchableOpacity onPress={() => handleEditTask(index)}>
<Text style={styles.editButton}>Edit</Text> {/* Edit button */}
</TouchableOpacity>
<TouchableOpacity onPress={() => handleDeleteTask(index)}>
<Text style={styles.deleteButton}>Delete</Text> {/* Delete button */}
</TouchableOpacity>
</View>
</View>
);
// Main UI rendering
return (
<View style={styles.container}>
<Text style={styles.heading}>Geeksforgeeks</Text> {/* App heading */}
<Text style={styles.title}>ToDo App</Text> {/* App title */}
<TextInput
style={styles.input}
placeholder="Enter task" // Placeholder text for the input field
value={task} // Bind input value to task state
onChangeText={(text) => setTask(text)} // Update task state on text change
/>
<TouchableOpacity
style={styles.addButton}
onPress={handleAddTask} // Call handleAddTask on button press
>
<Text style={styles.addButtonText}>
{editIndex !== -1 ? "Update Task" : "Add Task"} {/* Button text changes based on edit mode */}
</Text>
</TouchableOpacity>
<FlatList
data={tasks} // Pass tasks array as data
renderItem={renderItem} // Render each task using renderItem
keyExtractor={(_item, index) => index.toString()} // Unique key for each item
/>
</View>
);
};
// Styles for the components
const styles = StyleSheet.create({
container: {
flex: 1, // Take full screen height
padding: 40, // Add padding around the container
marginTop: 40, // Add margin at the top
},
title: {
fontSize: 24, // Font size for the title
fontWeight: "bold", // Bold font
marginBottom: 20, // Margin below the title
},
heading: {
fontSize: 30, // Font size for the heading
fontWeight: "bold", // Bold font
marginBottom: 7, // Margin below the heading
color: "green", // Green color for the heading
},
input: {
borderWidth: 3, // Border width for the input field
borderColor: "#ccc", // Border color
padding: 10, // Padding inside the input field
marginBottom: 10, // Margin below the input field
borderRadius: 10, // Rounded corners
fontSize: 18, // Font size for the input text
},
addButton: {
backgroundColor: "green", // Background color for the button
padding: 10, // Padding inside the button
borderRadius: 5, // Rounded corners
marginBottom: 10, // Margin below the button
},
addButtonText: {
color: "white", // Text color
fontWeight: "bold", // Bold font
textAlign: "center", // Center align the text
fontSize: 18, // Font size for the button text
},
task: {
flexDirection: "row", // Arrange items in a row
justifyContent: "space-between", // Space between items
alignItems: "center", // Align items vertically in the center
marginBottom: 15, // Margin below each task
fontSize: 18, // Font size for the task text
},
itemList: {
fontSize: 19, // Font size for the task text
},
taskButtons: {
flexDirection: "row", // Arrange buttons in a row
},
editButton: {
marginRight: 10, // Margin to the right of the edit button
color: "green", // Green color for the edit button text
fontWeight: "bold", // Bold font
fontSize: 18, // Font size for the edit button text
},
deleteButton: {
color: "red", // Red color for the delete button text
fontWeight: "bold", // Bold font
fontSize: 18, // Font size for the delete button text
},
});
// Export the App component as the default export
export default App;