0

I am fetching from an API that returns data in the form of an array. Lets say I have an array of 5 objects in this array which are exactly the same. I want to prevent duplicates by checking if duplicate exists before adding to my restaurants State. Below are snippets of my code:

const [restaurants, setRestaurants] = useState([])
const checkForDuplicateBusiness = (businessArray)=>{
    businessArray.forEach(singleBusiness=>{
      if(!restaurants.some(restaurant=> restaurant.id === singleBusiness.id)){
        setRestaurants(restaurants=>[...restaurants, singleBusiness])
        console.log(restaurants) //returns []
      }
    })
  }

The problem is that when I am checking with this line if(!restaurants.some(restaurant=> restaurant.id === singleBusiness.id)) the restaurants state is always empty. I understand that setState is async so the state is not updated by the time im checking it for the next iteration in the forEach loop. Im not sure what to do.

When I console log the restaurants via useEffect like:

useEffect(()=>{
  console.log(restaurants)
},[restaurants])

it will show 5 identical objects.

[
   0: {id: 'sDlYSTdgZCx0-3cRetKn8A'}
   1: {id: 'sDlYSTdgZCx0-3cRetKn8A'}
   2: {id: 'sDlYSTdgZCx0-3cRetKn8A'}
   3: {id: 'sDlYSTdgZCx0-3cRetKn8A'}
   4: {id: 'sDlYSTdgZCx0-3cRetKn8A'}
]

I am confused on this behavior because if i have exactly 5 copies of the object, that means my setRestaurants(restaurants=>[...restaurants, singleBusiness]) was working properly indicative from the spread operator. but my check if statement isnt?

The other solution I've thought of is to store my fetched data in a temporary array and perform the "preventDuplicate" logic in there, and then set it to my restaurants. But I'm not sure if this is the most efficient method. Is there a better way or the "React" way for this?

Any suggestions are appreciated. Thank you!

18
  • 1
    yes sorry typo. ive updated question Commented Apr 20, 2022 at 10:59
  • 1
    @jsN00b That won't work because prev is an array of objects, not ids. Commented Apr 20, 2022 at 11:01
  • 1
    Here's a three line solution: codesandbox.io/s/red-bash-nosq5y?file=/src/App.js Commented Apr 20, 2022 at 11:35
  • 2
    No, but removing duplicates from an array is a solved problem so this is a dupe anyway. You're welcome though :) Commented Apr 20, 2022 at 12:04
  • 1
    When you say multiple requests repeatedly, can you be a bit more specific? Also, I don't think this forces you to use a for loop; you could load everything first, then do the usual duplicate elimination. Commented Apr 22, 2022 at 6:15

1 Answer 1

1

The setStateSetter function gives you the updated state. Use it higher:

function uniqueById(items) {
  const set = new Set();
  return items.filter((item) => {
    const isDuplicate = set.has(item.id);
    set.add(item.id);
    return !isDuplicate;
  });
}

const updateRestaurantsUnique = (newItems) => {
  setRestaurants((restaurants) => {
    return uniqueById([...restaurants, ...newItems]);
  });
};

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.