I have an array of objects and this data should be stored in when new item is appended to the list. Also, when the application loads, this information have to be pushed back into the list. So, I use AsyncCallback, but it doesn't work properly. When I refresh application, all stored elements appear in the list except the last one. How can I return this item back to the list?
import React, { useState, useEffect } from 'react';
import { StyleSheet, View, Text, FlatList, Button, AsyncStorage } from 'react-native';
export default function HomeScreen() {
const [listItems, setListItems] = useState([
{
// example list item
id: '0',
text: 'Item 1'
},
]);
const [idx, incrIdx] = useState(1);
useEffect(() => {
getData();
}, []);
const pushItem = () => {
var data = new Object();
data.id = idx.toString();
data.text = "Item " + idx;
setListItems([...listItems, data]);
incrIdx(idx + 1);
storeData();
};
const storeData = async () => {
await AsyncStorage.setItem('listItems', JSON.stringify(listItems));
};
const getData = async () => {
const value = await AsyncStorage.getItem('listItems');
if(value !== null) {
setListItems([...listItems, JSON.parse(value)]);
}
};
return (
<View style={styles.container}>
<FlatList
data={listItems}
renderItem={({item}) =>
<View>
<Text>{item.text}</Text>
</View>
}
keyExtractor={item => item.id}
/>
<Button
title="Push data"
onPress={pushItem}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});
Did you look at what AsyncStorage.setItem
is actually setting?
My guess is that it's not using the latest listItems state because hook setters are asynchronous (just like the old setState
).
To express logic that should take effect when state is updated, use the useEffect
api.
useEffect(() => {
// Instead of calling storeData() with stale state
AsyncStorage.setItem('listItems', JSON.stringify(listItems));
}, [listItems]);