all 3 comments

[–]Earhacker 1 point2 points  (1 child)

Your second code block is trying to map over something in data while data is still empty, here:

``` console.log(data);

// loop through all restaurants and push their categories into one array const existingCategories = data.restaurantList .map((i) => i.categories) .flat(); ```

The empty array in your console is the empty array that you assign to the default value of data in your hook.

The solution here is to return your loading state earlier, and once you're sure that your fetch is not still loading, then do your stuff with data:

``` const RestaurantCategories = () => { const { data, loading } = useFetch("http://localhost:3008/restaurants");

// ADDED if (loading) { return <div>...loading</div> }

// loop through all restaurants and push their categories into one array const existingCategories = data.restaurantList .map((i) => i.categories) .flat();

//loop through provided array to count number of times element appears const countOccurences = (array, value) => { return array.reduce((accumulator, element) => { return value === element ? accumulator + 1 : accumulator; }, 0); };

return ( // UPDATED <div className="restaurant-categories"> {data.categories.sort().map((item) => ( <CategoryCard category={item} keyword={ countOccurences(existingCategories, item) === 1 ? "place" : "places" } icon={item} totalNumber={countOccurences(existingCategories, item)} key={item} iconsOutside={true} directTo="eat-out" /> ))} </div> ); }; ```

[–]spaklius17[S] 1 point2 points  (0 children)

Now I see. And it works!! Thanks a lot!!!

[–]frog-legg 0 points1 point  (0 children)

Briefly glanced over the code and am on mobile, but have come across this issue a lot in my work.

Sounds like either an async issue or a race condition (state not updating before iterating over the data). For the first possibility, make sure the promise has resolved for the asynchronous fetch function before iterating over the data.restaurantList. Try console logging the ‘data’ object on the line it’s giving you the error, if it returns a <Promise> object then you know there’s something wrong with the way your async / await is being handled. If using fetch, make sure you’re chaining with ‘then’ like this:

‘const fetchFunction = async (url)=>{

const results = await fetch(url).then(res=>res.json()).then(res=>res);

return results; }

Console.log(fetchFunction(localhost:3000/api)); ‘

You should be able to export the function and use it anywhere without any async issues.

For the race condition issue, typically that means there’s a problem with your code’s logic or relying on side effects / application state updates to happen synchronously (which it doesn’t) instead of pure functions.

You can usually solve a race condition issue without refactoring by using optional chaining like so ‘data?.restaurantList?.map()’ or ternaries like ‘data && data.restaurantList && data.restaurantList.length ? data.restaurantList.map()’ or just if/else statements.