[SOLVED] Why this map function does not work, although code looks fine?

Issue

This Content is from Stack Overflow. Question asked by Deepeshkumar Pakhare

In my react functional component I am returning a list of notifications.
The code runs fine but the map() function does not show desired effect, no list is seen… I get results on console but the object called “data” I am generating just doesnt works properly with map() or may be some other issue is there which i can not see..
My code is :

import React from 'react'
import { useEffect } from 'react';
import { useState } from 'react'

export default function Notifications() {

  var data = [];
  var categoryNames = [];
  var budgetsArray = [];
  var datesArray = [];

  const sessionInfo = JSON.parse(window.localStorage.getItem("session"));

  useEffect(
    () => {
      handleShowNotification();
    }
  )

  async function getAllNotifications() {
    var myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");
    myHeaders.append("Cookie", "connect.sid=s%3A80dace41-48b4-47d8-a444-f8febddbfd90.1vgh6QFP%2FtUfsEdt%2B%2F91KgBJjKFVnMm6vghCiOGLmP8");

    var raw = JSON.stringify({
      "session_id": sessionInfo._id,
    });

    var requestOptions = {
      method: 'POST',
      headers: myHeaders,
      body: raw,
      redirect: 'follow'
    };

    var response = await fetch("http://localhost:8080/myNotifications", requestOptions);
    var result = await response.json()
    console.log("all notifications are " + result.data.notifications);
    return result.data.notifications;
  }

  async function getCategoryName(category_id) {
    var myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");
    myHeaders.append("Cookie", "connect.sid=s%3Adb8f2f2e-3680-4dd7-8b7d-cb022010cc7a.4AKLofa96yxCRAhjQJdkKKyaeOJpc0g%2FqQxJ9klQpmk");

    var raw = JSON.stringify({
      "session_id": sessionInfo._id,
      "category_id": category_id
    });

    var requestOptions = {
      method: 'POST',
      headers: myHeaders,
      body: raw,
      redirect: 'follow'
    };

    var response = await fetch("http://localhost:8080/fetchCategory", requestOptions);
    var result = await response.json();
    return result.data.category.category_name;
  }

  async function getBudget(categoryId) {
    var myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");
    myHeaders.append("Cookie", "connect.sid=s%3A80dace41-48b4-47d8-a444-f8febddbfd90.1vgh6QFP%2FtUfsEdt%2B%2F91KgBJjKFVnMm6vghCiOGLmP8");

    var raw = JSON.stringify({
      "session_id": sessionInfo._id,
      "category_id": categoryId
    });

    var requestOptions = {
      method: 'POST',
      headers: myHeaders,
      body: raw,
      redirect: 'follow'
    };

    var response = await fetch("http://localhost:8080/getBudget", requestOptions)
    var result = await response.json();
    return result.data.budget.amount;
  }



 async function handleShowNotification() {
    var notifications = await getAllNotifications();
    var count = 0;
    for (var notification of notifications) {
      count++;
      var categoryName = await getCategoryName(notification.category_id);
      console.log("category name "+categoryName);
      categoryNames.push(categoryName);
      var budgetAmount = await getBudget(notification.category_id);
      console.log("budget amount "+budgetAmount);
      budgetsArray.push(budgetAmount);
      var date = notification.date_of_creation;
      console.log("date "+date);
      datesArray.push(date);
    }
    for (var i=0; i<count; i++) {
        data.push({
          categoryName:categoryNames[i],
          budgetAmount:budgetsArray[i],
          date:datesArray[i],
        });
    }
    console.log("length of data is "+data.length)
  }

  function getFullData(item) {
    return (<li>The catgeory name is {item.categoryName}and budget is{item.budgetAmount}</li>);
  }

  return (
    <div>
      <br />
      <br />
      <div className="row">
        {/*<button onClick={handleShowNotification} style={{ width: "50%" }}>Show notifications</button>*/}
        <ul>
         //Problem is here, this is not shown
        {data.map(getFullData)}
        </ul>
      </div>
    </div>
  )
}



Solution

Issue

data and the other variables are redeclared each render cycle as local variables. They are also mutated each render cycle. The useEffect hook is also missing a dependency array and updates the state which leads to render looping.

Solution

Convert data and any of the other variables to a React state variable using the useState hook. When state is updated this will trigger React to rerender the component with the updated state value.

const [data, setData] = useState([]);

Add a dependency array to the useEffect hook so it’s not triggering a state update each and every render cycle.

useEffect(() => {
  handleShowNotification();
}, []);

Each mapped element needs to have a proper React key. Since the data array elements haven’t any unique id properties I suggest adding on and populating that property when adding new items to the data state.

Example:

import { nanoid } from 'nanoid';

...

function handleShowNotification() {
  setData((data) =>
    data.concat({
      id: nanoid(),
      categoryName: "food",
      budgetAmount: 1000
    })
  );
}

...

function getFullData(item) {
  return (
    <li key={item.id}>
      The catgeory name is {item.categoryName}and budget is{item.budgetAmount}
    </li>
  );
}

...

<ul>{data.map(getFullData)}</ul>

Edit why-this-map-function-does-not-work-although-code-looks-fine


This Question was asked in StackOverflow by Deepeshkumar Pakhare and Answered by Drew Reese It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?