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>
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.