Building a To-Do App in React Native with Theming options and AsyncStorage

Building a To-Do App in React Native with Theming options and AsyncStorage

Introduction

In this guide, we will walk through creating a To-Do App in React Native. This app will feature:

Adding, deleting, and marking tasks as comp…


This content originally appeared on DEV Community and was authored by Arun Kumar

Building a To-Do App in React Native with Theming options and AsyncStorage

Introduction

In this guide, we will walk through creating a To-Do App in React Native. This app will feature:

  • Adding, deleting, and marking tasks as completed
  • Dark mode support using a custom switch
  • Persistent storage with AsyncStorage
  • Smooth UI with custom styling and animations

Let's get started! 🚀

Prerequisites

Before we begin, ensure you have the following installed:

  • Node.js
  • Expo CLI
  • A code editor (e.g., VS Code)
  • An emulator or a physical device with Expo Go

Step 1: Set Up a New React Native Project

Run the following command to create a new React Native project using Expo:

npx create-expo-app todo-app
cd todo-app
npm install

Step 2: Install Required Dependencies

We will use AsyncStorage for local data storage and Expo Icons for UI icons.

npm install @react-native-async-storage/async-storage
npm install @expo/vector-icons

Step 3: Create the Main App Component

Create an App.js file and paste the following code:

import React, { useState, useEffect } from 'react';
import {
  View, Text, FlatList, TouchableOpacity, TextInput, StyleSheet, Modal, Image, StatusBar, SafeAreaView
} from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { AntDesign } from '@expo/vector-icons';
import CustomSwitch from './CustomSwitch';

const App = () => {
  const [tasks, setTasks] = useState([]);
  const [isModalVisible, setModalVisible] = useState(false);
  const [input, setInput] = useState('');
  const [darkMode, setDarkMode] = useState(false);

  const toggleTheme = () => setDarkMode(!darkMode);

  const addTask = () => {
    if (!input.trim()) return;
    const newTask = { id: Date.now(), text: input, completed: false };
    setTasks([...tasks, newTask]);
    setInput('');
    setModalVisible(false);
  };

  const deleteTask = (id) => setTasks(tasks.filter((task) => task.id !== id));

  const toggleCompleted = (id) => {
    setTasks(tasks.map(task => task.id === id ? { ...task, completed: !task.completed } : task));
  };

  useEffect(() => {
    const loadTasks = async () => {
      try {
        const storedTasks = await AsyncStorage.getItem('tasks');
        if (storedTasks) setTasks(JSON.parse(storedTasks));
      } catch (error) {
        console.error('Error loading tasks:', error);
      }
    };
    loadTasks();
  }, []);

  useEffect(() => {
    const saveTasks = async () => {
      try {
        await AsyncStorage.setItem('tasks', JSON.stringify(tasks));
      } catch (error) {
        console.error('Error saving tasks:', error);
      }
    };
    saveTasks();
  }, [tasks]);

  return (
    <SafeAreaView style={[styles.container, darkMode ? styles.darkBackground : styles.lightBackground]}>
      <StatusBar barStyle={darkMode ? "light-content" : "dark-content"} backgroundColor={darkMode ? "#b5b7f5" : "#9395d3"} />
      <View style={[styles.header, darkMode ? styles.darkBackgroundAccent : styles.lightBackgroundAccent]}>
        <Text style={[styles.headerText, darkMode ? styles.darkText : styles.lightText]}>Todo App</Text>
        <CustomSwitch value={darkMode} onValueChange={toggleTheme} />
      </View>
      <FlatList
        data={tasks}
        keyExtractor={(item) => item.id.toString()}
        renderItem={({ item }) => (
          <View style={[styles.task, darkMode ? styles.cardBackgroundDark : styles.cardBackgroundLight]}>
            <Text style={[styles.taskText, item.completed && styles.completedTask, darkMode ? styles.darkText : styles.lightText]}>{item.text}</Text>
            <View style={styles.taskActions}>
              <TouchableOpacity onPress={() => toggleCompleted(item.id)}>
                <Image style={styles.tickImage} source={require('./assets/Completed.png')} />
              </TouchableOpacity>
              <TouchableOpacity onPress={() => deleteTask(item.id)}>
                <Image style={styles.deleteImage} source={require('./assets/Delete.png')} />
              </TouchableOpacity>
            </View>
          </View>
        )}
      />
      <TouchableOpacity style={[styles.addButton, darkMode ? styles.darkBackgroundAccent : styles.lightBackgroundAccent]} onPress={() => setModalVisible(true)}>
        <AntDesign name="plus" size={24} color="white" />
      </TouchableOpacity>
    </SafeAreaView>
  );
};

export default App;

Step 4: Create the Custom Switch Component

Create a file called CustomSwitch.js and paste the following code:

import React, { useRef, useEffect } from 'react';
import { TouchableOpacity, View, StyleSheet, Animated } from 'react-native';
import Feather from '@expo/vector-icons/Feather';
import Ionicons from '@expo/vector-icons/Ionicons';

const CustomSwitch = ({ value, onValueChange }) => {
  const translateX = useRef(new Animated.Value(value ? 20 : 0)).current;

  useEffect(() => {
    Animated.timing(translateX, {
      toValue: value ? 20 : 0,
      duration: 200,
      useNativeDriver: true,
    }).start();
  }, [value]);

  return (
    <TouchableOpacity style={[styles.switch, value ? styles.onBackground : styles.offBackground]} onPress={onValueChange}>
      <Animated.View style={[styles.toggle, { transform: [{ translateX }] }]}> 
        {value ? <Ionicons name="moon" size={15} color="black" /> : <Feather name="sun" size={15} color="black" />}
      </Animated.View>
    </TouchableOpacity>
  );
};

export default CustomSwitch;

Step 5: Run the App

Now, start your development server by running:

npx expo start

Scan the QR code with Expo Go on your phone to preview the app!

Conclusion

Congratulations! 🎉 You have successfully built a To-Do App with React Native featuring dark mode, persistent storage, and smooth UI. Happy coding! 🚀


This content originally appeared on DEV Community and was authored by Arun Kumar


Print Share Comment Cite Upload Translate Updates
APA

Arun Kumar | Sciencx (2025-01-31T10:26:40+00:00) Building a To-Do App in React Native with Theming options and AsyncStorage. Retrieved from https://www.scien.cx/2025/01/31/building-a-to-do-app-in-react-native-with-theming-options-and-asyncstorage/

MLA
" » Building a To-Do App in React Native with Theming options and AsyncStorage." Arun Kumar | Sciencx - Friday January 31, 2025, https://www.scien.cx/2025/01/31/building-a-to-do-app-in-react-native-with-theming-options-and-asyncstorage/
HARVARD
Arun Kumar | Sciencx Friday January 31, 2025 » Building a To-Do App in React Native with Theming options and AsyncStorage., viewed ,<https://www.scien.cx/2025/01/31/building-a-to-do-app-in-react-native-with-theming-options-and-asyncstorage/>
VANCOUVER
Arun Kumar | Sciencx - » Building a To-Do App in React Native with Theming options and AsyncStorage. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/01/31/building-a-to-do-app-in-react-native-with-theming-options-and-asyncstorage/
CHICAGO
" » Building a To-Do App in React Native with Theming options and AsyncStorage." Arun Kumar | Sciencx - Accessed . https://www.scien.cx/2025/01/31/building-a-to-do-app-in-react-native-with-theming-options-and-asyncstorage/
IEEE
" » Building a To-Do App in React Native with Theming options and AsyncStorage." Arun Kumar | Sciencx [Online]. Available: https://www.scien.cx/2025/01/31/building-a-to-do-app-in-react-native-with-theming-options-and-asyncstorage/. [Accessed: ]
rf:citation
» Building a To-Do App in React Native with Theming options and AsyncStorage | Arun Kumar | Sciencx | https://www.scien.cx/2025/01/31/building-a-to-do-app-in-react-native-with-theming-options-and-asyncstorage/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.