Reputation: 317
I am facing issue of duplicate element when updating the state in useEffect, WHat i am trying to do is I get data from firebase and iterate through the data and updating an array with useState, and if the element already exists in in the array, then skip to add that and move to next element. Codes are below
import React, {useState, useEffect} from 'react';
import {View, FlatList} from 'react-native';
const Users = props => {
const [users, setUsers] = useState([]);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
(async () => {
const dbUsers = await db.collection('users').get();
if (dbUsers.length !== 0) {
dbUsers.map((filteredUser) => {
if (dbUsers.exists) {
const isUserExists = users.find((u) => u.key === dbUsers.id);
if (!isUserExists) {
setUsers((prevState) => [
...prevState,
new ContactsList(
dbUsers.id,
dbUsers.data().name,
dbUsers.data().number,
dbUsers.data().profileAvtar,
dbUsers.data().onesignalId,
),
]);
}
}
});
}
})();
}, [users]});
setUsers, not reflecting the updated state in mapping the array.
Upvotes: 0
Views: 136
Reputation: 2663
When you want to update an array of values, always prefer updating it with a single call to setUsers
instead of appending values one at a time using multiple calls. With your current implementation, a new call to db.collection('users').get()
is triggered for each user record it returns, leading to the duplication you're seeing.
Try this:
const Users = props => {
const [users, setUsers] = useState([]);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
(async () => {
const dbUsers = await db.collection('users').get();
const updatedUsers = dbUsers.map(dbUser => {
// look for an existing user
const existingUser = users.find(u => u.key === dbUser.id);
// if we already have the user locally, don't update
if (existingUser) {
return existingUser;
}
// otherwise, create and return a new user from the remote data
return new ContactsList(
dbUser.id,
dbUser.data().name,
dbUser.data().number,
dbUser.data().profileAvtar,
dbUser.data().onesignalId,
);
});
setUsers(updatedUsers);
})();
}, [users]);
}
As @lissettdm pointed out, make sure ContactsList
has a key
field that is the same type (string or integer) as dbUser.id
.
Upvotes: 1