Create ToDo App using React Native

Last Updated : 20 Feb, 2026

A ToDo App using React Native is a mobile application that helps users manage daily tasks efficiently. It allows users to add, update, and delete tasks while providing a smooth cross-platform experience on both Android and iOS using a single codebase.

  • Helps users organize tasks by adding, editing, and deleting to-do items easily.
  • Uses React Native components and state management for responsive UI and real-time updates.
  • Supports cross-platform development, saving time and effort with one codebase for multiple devices.

Here, We start implementing the React Native ToDo App step by step, from setup to task management features.

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.

1. 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.

2. For iOS users, simply scan the QR code using the Camera app .

3. 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.

JavaScript
// Importing useState hook from React
import { useState } from "react"; 
// Importing StyleSheet for styling components
import {
  // Importing View component for layout
  View, 
  // Importing Text component for displaying text
  Text, 
  // Importing TextInput component for user input
  TextInput,  
  // Importing TouchableOpacity for button-like behavior
  TouchableOpacity, 
  // Importing FlatList for rendering lists
  FlatList, 
  // Importing StyleSheet for styling components
  StyleSheet,   
} from "react-native"; 


StyleSheet: Create a StyleSheet to style components like container, title, heading, input, addButton, addButtonText, task, itemList, taskButton, editButton and deleteButton.

JavaScript
// Styles for the components
const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 40, 
    marginTop: 40, 
  },
  title: {
    fontSize: 24, 
    fontWeight: "bold", 
    marginBottom: 20, 
  },
  heading: {
    fontSize: 30, 
    fontWeight: "bold", 
    marginBottom: 7, 
    color: "green", 
  },
  input: {
    borderWidth: 3, 
    borderColor: "#ccc", 
    padding: 10, 
    marginBottom: 10, 
    borderRadius: 10, 
    fontSize: 18, 
  },
  addButton: {
    backgroundColor: "green", 
    padding: 10, 
    borderRadius: 5, 
    marginBottom: 10, 
  },
  addButtonText: {
    color: "white", 
    fontWeight: "bold", 
    textAlign: "center", 
    fontSize: 18, 
  },
  task: {
    flexDirection: "row", 
    justifyContent: "space-between", 
    alignItems: "center", 
    marginBottom: 15, 
    fontSize: 18, 
  },
  itemList: {
    fontSize: 19, 
  },
  taskButtons: {
    flexDirection: "row", 
  },
  editButton: {
    marginRight: 10, 
    color: "green", 
    fontWeight: "bold", 
    fontSize: 18,
  },
  deleteButton: {
    color: "red", 
    fontWeight: "bold", 
    fontSize: 18, 
  },
});

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.
JavaScript
<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.

JavaScript
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.

JavaScript
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.

JavaScript
const handleEditTask = (index) => {
    // Get the task to be edited
    const taskToEdit = tasks[index]; 
    // Set the task in the input field
    setTask(taskToEdit); 
    // Set the index of the task being edited
    setEditIndex(index); 
};

handleDeleteTask: Function to handle deleting a task.

JavaScript
const handleDeleteTask = (index) => {
    const updatedTasks = [...tasks];
    // Remove the task at the specified index
    updatedTasks.splice(index, 1); 
     // Update the tasks state
    setTasks(updatedTasks);
};

useState: useState is used to manage the state of the task input, list of tasks, and index of the task being edited.

JavaScript
// 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:

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;

Output:

Comment

Explore