1

Early today I finished a To-Do list tutorial on YouTube for React Native and I decided to try add some features to it and so far it has been going well, I decided to export my app into an APK to have some fun seeing it working and I've realised that when the app closes I lose all of my saved To-Do items! Would there be anyway of doing that locally on the users Android device?

import React, { useState } from "react";
import {
  KeyboardAvoidingView,
  Platform,
  StyleSheet,
  Text,
  TextInput,
  Keyboard,
  TouchableOpacity,
  View,
} from "react-native";
import Modal from "react-native-modal";
import Task from "./components/Task";
import { faTrophy } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome";

export default function App() {
  const [task, setTask] = useState();
  const [taskItems, setTaskItems] = useState([]);
  const [modalVisable, setModalVisable] = useState(false);
  const [itemToDelete, setItemToDelete] = useState();

  const handleAddTask = () => {
    Keyboard.dismiss();
    setTaskItems([...taskItems, task]);
    setTask(null);
  };

  const completeTask = (index) => {
    let itemsCopy = [...taskItems];
    itemsCopy.splice(index, 1);
    setTaskItems(itemsCopy);
    closeModal();
  };

  const closeModal = () => {
    setModalVisable(false);
  };

  const handleRemoveTask = (index) => {
    setModalVisable(true);
  };

  return (
    <View style={styles.container}>
      <View style={styles.tasksWrapper}>
        <Text style={styles.sectionTitle}>Your Tasks</Text>

        <View style={styles.items}>
          {taskItems.map((item, index) => {
            return (
              <TouchableOpacity
                key={index}
                onPress={() => {
                  handleRemoveTask(index);
                  setItemToDelete(index);
                }}
              >
                <Task text={item} />
              </TouchableOpacity>
            );
          })}
        </View>
      </View>

      <KeyboardAvoidingView
        behavior={Platform.OS === "ios" ? "padding" : "height"}
        style={styles.writeTaskWrapper}
      >
        <TextInput
          style={styles.input}
          placeholder={"Add a task!"}
          value={task}
          onChangeText={(text) => setTask(text)}
        />
        <TouchableOpacity onPress={() => handleAddTask()}>
          <View style={styles.addWrapped}>
            <Text style={styles.addText}>+</Text>
          </View>
        </TouchableOpacity>
      </KeyboardAvoidingView>

      <View style={styles.modalWrapper}>
        <Modal
          style={styles.modal}
          isVisible={modalVisable}
          onBackdropPress={closeModal}
        >
          <Text style={styles.modalText}>Have you completed this task?</Text>
          <FontAwesomeIcon
            icon={faTrophy}
            style={styles.trophyIcon}
            size={96}
          />
          <View style={styles.horizontalRule}>
            <Text style={styles.modalDescription}>
              If you confirm this task is complete it will be deleted and
              removed from the app permanently
            </Text>
          </View>
          <View style={styles.buttonArea}>
            <TouchableOpacity
              style={styles.closeButton}
              onPress={() => closeModal()}
            >
              <Text style={styles.buttonText}>Cancel</Text>
            </TouchableOpacity>
            <TouchableOpacity
              style={styles.completeButton}
              onPress={() => completeTask(itemToDelete)}
            >
              <Text style={styles.buttonText}>Complete Task</Text>
            </TouchableOpacity>
          </View>
        </Modal>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#E8EAED",
  },
  tasksWrapper: {
    paddingTop: 80,
    paddingHorizontal: 20,
  },
  sectionTitle: {
    fontSize: 24,
    fontWeight: "bold",
  },
  items: {
    marginTop: 30,
  },
  writeTaskWrapper: {
    position: "absolute",
    bottom: 50,
    width: "100%",
    flexDirection: "row",
    justifyContent: "space-around",
    alignItems: "center",
  },
  input: {
    paddingVertical: 15,
    paddingHorizontal: 15,
    backgroundColor: "#FFF",
    borderRadius: 60,
    borderColor: "#C0C0C0",
    borderWidth: 1,
    textAlign: "center",
    width: "70%",
  },
  addWrapped: {
    width: 60,
    height: 60,
    backgroundColor: "#FFF",
    borderRadius: 60,
    borderColor: "#C0C0C0",
    borderWidth: 1,
    justifyContent: "center",
    alignItems: "center",
  },
  addText: {},
  modalWrapper: {},
  modal: {
    justifyContent: "flex-start",
    alignSelf: "center",
    top: 100,
    borderRadius: 5,
    backgroundColor: "#FFF",
    maxWidth: 350,
    maxHeight: 300,
    padding: 25,
  },
  modalText: {
    fontSize: 20,
    fontWeight: "normal",
    textAlign: "center",
  },
  buttonText: {
    fontWeight: "bold",
    textAlign: "center",
  },
  buttonArea: {
    position: "relative",
    flexWrap: 'nowrap',
    alignContent: "center",
    justifyContent: "space-between",
    flexDirection: "row",
    paddingTop: 5,
    minWidth: 100,
    maxWidth: 350,
    top: 5,
  },
  completeButton: {
    justifyContent: "center",
    alignSelf: "center",
    width: 140,
    height: 36,
    borderRadius: 10,
    backgroundColor: "#B096F9",
  },
  closeButton: {
    justifyContent: "center",
    alignSelf: "center",
    width: 140,
    height: 36,
    borderRadius: 10,
    backgroundColor: "#FF8989",
  },
  trophyIcon: {
    padding: 75,
    color: "#F8C511",
    alignSelf: "center",
  },
  modalDescription: {
    textAlign: "center",
    fontSize: 14,
    borderColor: "#AFAFAF",
    borderTopWidth: 1,
    borderBottomWidth: 1,
  },
});
parsley72
  • 8,449
  • 8
  • 65
  • 98
StanLachie
  • 57
  • 2
  • 7

1 Answers1

1

Check out React Native Async Storage