1

I am newbie in React Native and I am trying to store and get an array with AsyncStorage in ReactNative.

I have two problems.

First, I do not know why but when I storage data, it only works the second time but I am calling first the set of useState.

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

Second, how can I call the getData function to get all the data and show it? Are there something like .onInit, .onInitialize... in ReactNative? Here is my full code

const [task, setTask] = useState();
const [taskItems, setTaskItems] = useState([]);

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

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

  const storeData = async (value) => {
    try {
      await AsyncStorage.setItem('@tasks', JSON.stringify(value))
      console.log('store', JSON.stringify(taskItems));
    } catch (e) {
      console.log('error');
    }
  }

  const getData = async () => {
    try {
      const value = await AsyncStorage.getItem('@tasks')
      if(value !== null) {
        console.log('get', JSON.parse(value));
      } 
    } catch(e) {
      console.log('error get');
    }
  }
Tomas
  • 13
  • 6

2 Answers2

1

Even if you're update state setTaskItems([...taskItems, task]) before save new data in local storage, storeData(taskItems) executed before state updated and save old state data.

Refactor handleAddTask as below.

  const handleAddTask = () => {
   Keyboard.dismiss();

const newTaskItems = [...taskItems, task]
    setTaskItems(newTaskItems);
    storeData(newTaskItems);
  };

Fiston Emmanuel
  • 4,242
  • 1
  • 8
  • 14
  • Thanks for your answer, now I can store data correctly, but do you know how can I solve the other problem? I want to get the data in the storage at the first to be able to show it when app starts. – Tomas Feb 15 '22 at 07:38
  • Glad to hear that @Tomas. Can you approve this answer for future readers' reference. – Fiston Emmanuel Feb 15 '22 at 10:56
  • For other problems, I offer 1:1 personal support service. You can reach me at emmbyiringiro@gmail.com – Fiston Emmanuel Feb 15 '22 at 10:58
  • I will approve the answer when I had both problems solved. – Tomas Feb 15 '22 at 11:15
1

Updating state in React is not super intuitive. It's not asynchronous, and can't be awaited. However, it's not done immediately, either - it gets put into a queue which React optimizes according to its own spec.

That's why BYIRINGIRO Emmanuel's answer is correct, and is the easiest way to work with state inside functions. If you have a state update you need to pass to more than one place, set it to a variable inside your function, and use that.

If you need to react to state updates inside your component, use the useEffect hook, and add the state variable to its dependency array. The function in your useEffect will then run whenever the state variable changes.

Abe
  • 4,500
  • 2
  • 11
  • 25
  • Thanks for your explanation, now I need to get data at the "init" of the app. – Tomas Feb 15 '22 at 07:40
  • It seems to me that you want the data on the initialization of the component, and not the app. You can use `useEffect` to run your methods on mount of the component. In your case this would look something like `useEffect(() => AsyncStorage.getItem('@tasks').then(data => setTaskItems(JSON.parse(data)), [setTaskItems]);` [Here are the docs for useEffect.](https://reactjs.org/docs/hooks-effect.html) If you want it at the init of the app, you can call it in App.jsx or even index.js. – Abe Feb 15 '22 at 16:21