Issue
So I am trying to add to a useState array of objects however it is getting overwritten everytime I try to add something new to it.
I define my state
const [habits, setHabits] = useState([]);
make multiple calls to return a data object
asyncStorageKeys.forEach(key => {
getDataObject(key, habits, setHabits);
});
getDataObject looks like this
export const getDataObject = async (key, data, setData) => {
try {
const jsonValue = await AsyncStorage.getItem(key);
return jsonValue != null ? setData([...data, JSON.parse(jsonValue)]) : null;
} catch (e) {
console.error('Error returning data object in AsyncStorage, error: ' + e);
}
};
But when I console.log using
useEffect(() => {
console.log(habits);
}, [habits]);
It shows that the array is just being overwritten everytime
LOG []
LOG [{"daysPerWeek": 3, "name": "another one"}]
LOG [{"daysPerWeek": 7, "name": "test"}]
LOG [{"daysPerWeek": 6, "name": "testing"}]
LOG [{"daysPerWeek": 6, "name": "tests"}]
I have looked on react.dev (https://react.dev/learn/updating-arrays-in-state) for the recommended way to do this however it is not working for me.
Solution
Whenever you call setData([...data, JSON.parse(jsonValue)])
you add the current item to the original state and then set it as the state, and the last addition would overwrite all the others. For example, if you have a state of [1, 2, 3]
, and you want to add the values - 4, 5, 6, the end state would be [1, 2, 3, 6]
. See Updating state based on the previous state.
To prevent that you can you can use an updater function, that takes the last updated state on each iteration:
setData(prev => [...prev, JSON.parse(jsonValue)])
However, it's better make all async calls at once using Array.map()
, wait for all of them to finish with Promise.all()
, and then update the state while filtering null
values:
export const getDataObjects = async() => {
try {
const values = await Promise.all( // wait for all promises to resolve
// create an array of promises
asyncStorageKeys.map(key =>
AsyncStorage.getItem(key).then(v => JSON.parse(v))
)
);
// add all non null values to previous state
setData(prev => [...prev, ...values.filter(v => v !== null)])
} catch (e) {
console.error('Error returning data object in AsyncStorage, error: ' + e);
}
};
Answered By - Ori Drori
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.