Home > Software engineering >  React Native, not able to store and fetch data correctly with async-storage
React Native, not able to store and fetch data correctly with async-storage

Time:07-04

I am using the below code to create a simple to-do list. Everything works fine except the async-storage components since the tasks are either not being saved or not being fetched. Could anyone kindly point out any modifications I can do to the useEffects to fix this issue?

/* eslint-disable prettier/prettier */
import React, {useState, useEffect} from 'react';
import {View, StyleSheet, FlatList, Alert} from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import uuid from 'react-native-uuid';
import Header from './components/header.js';
import Task from './components/task.js';
import Add from './components/add.js';

const App = () => {
const [tasks, setTasks] = useState([]);

const addTask = (text) => {
  if (!text) {
    Alert.alert(null,'No task entered\nPlease enter a task',);
  } else {
    setTasks(prevState => {
      return [...prevState, {id: uuid.v4(), title: text}];
    });
  }
};

const removeTask = (id) => {
  setTasks(prevState =>{
      return prevState.filter(task => task.id!=id);
  }); 
};

useEffect(() => {
 const saveTasks = async () => {
    await AsyncStorage.setItem('TASKS', JSON.stringify(tasks));
  }
  saveTasks();
}, [tasks]);

useEffect(() => {
  const fetchTasks = async () =>{
    const saved = await AsyncStorage.getItem('TASKS');
    setTasks(JSON.parse(saved));
  }
  fetchTasks();
}, []);

 return (
    <View style={styles.container}>
      <Header/>
      <Add addTask={addTask} />
      <FlatList
        data={tasks}
        renderItem={({ item }) => <Task text={item.title} removeTask={removeTask} id={item.id}/>}
        keyExtractor={task => task.id}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

export default App;

CodePudding user response:

Problem

The problem is caused by the below useEffect. It saves tasks in storage every time tasks changes, but also on first render where tasks is equal to [], the value given to useState.

useEffect(() => {
 const saveTasks = async () => {
    await AsyncStorage.setItem('TASKS', JSON.stringify(tasks));
  }
  saveTasks();
}, [tasks]);

Solution

An easy way to solve this issue is to remove the above useEffect, and change addTask and removeTask as follow:

const addTask = (text) => {
  if (!text) {
    Alert.alert(null,'No task entered\nPlease enter a task',);
  } else {
    const newTasks = [...tasks, {id: uuid.v4(), title: text}];
    await AsyncStorage.setItem('TASKS', JSON.stringify(newTasks));
    setTasks(newTasks);
  }
};
const removeTask = (id) => { 
  const newTasks = tasks.filter(task => task.id!=id);
  await AsyncStorage.setItem('TASKS', JSON.stringify(newTasks));
  setTasks(newTasks); 
};
  • Related