I am trying to develop a list of products to display in react js.
I am using local data.json
file for now but will fetch from an API in future.
my data.json sample is
{
"Result": "OK",
"Code": 200,
"famproduct": [
{
"Prd_Code": "701012583",
"Descr": "B FIT ADULT PANTS L10 ",
"Company_Name": "ANEV",
"Packing": "",
"Sr_No": 1,
"Sale_Rate": 450.1488,
"Max_Rate": 605,
"Batch_No": "",
"Expiry": " -",
"Gst_Perc": 12,
"P_Code": "AYAN0027"
},..and other lots of data..,
{
"Prd_Code": "701012584",
"Descr": "B FIT ADULT PANTS XL10 ",
"Company_Name": "ANEV",
"Packing": "",
"Sr_No": 1,
"Sale_Rate": 491.0714,
"Max_Rate": 660,
"Batch_No": "",
"Expiry": " -",
"Gst_Perc": 12,
"P_Code": "AYAN0027"
}
],
"Message": "List Record"
}
I am trying to display this json data in a list and added buttons in every list item.
ISSUE
Issue is whenever I click a listitem button, it shows very slow response.
What I did
I tried to reduce json data and it worked properly. So I guess there is issue with this big json data.
What should I do so my interaction with buttons don’t lag.?
UPDATE
here i am showing the issue i am facing
ISSUE CLICK HERE
some part of my code shown below
import React, { useState } from "react";
import {
Container,
Typography,
List,
ListItem,
Paper,
Button,
IconButton,
TextField,
} from "@mui/material";
import { Add } from "@mui/icons-material";
import DeleteIcon from "@mui/icons-material/Delete";
import AddShoppingCartIcon from "@mui/icons-material/AddShoppingCart";
import mydata from "../data.json";
import "./style.css";
interface Product {
Descr: string;
Prd_Code: string;
Company_Name: string;
Gst_Perc: number;
Max_Rate: number;
Sale_Rate: number;
Batch_No?: string;
Expiry?: string;
}
const ProductList: React.FC = () => {
const [products, setProducts] = useState<Product[]>(mydata.famproduct || []);
const [qty, setQty] = useState<{ [key: string]: number }>({});
const [expandedProduct, setExpandedProduct] = useState<string | null>(null);
const handleAddToQty = (Prd_Code: string) => {
setQty((prevQty) => ({
...prevQty,
[Prd_Code]: (prevQty[Prd_Code] || 0) + 1,
}));
};
const handleIncreaseQuantity = (Prd_Code: string) => {
setQty((prevQty) => ({
...prevQty,
[Prd_Code]: prevQty[Prd_Code] + 1,
}));
};
const handleDecreaseQuantity = (Prd_Code: string) => {
setQty((prevQty) => {
const newQuantity = (prevQty[Prd_Code] || 0) - 1;
if (newQuantity > 0) {
return {
...prevQty,
[Prd_Code]: newQuantity,
};
} else {
const { [Prd_Code]: _, ...rest } = prevQty;
return rest;
}
});
};
const handleQuantityChange = (event: React.ChangeEvent<HTMLInputElement>, Prd_Code: string) => {
const value = parseInt(event.target.value, 10);
if (value > 0) {
setQty((prevQty) => ({
...prevQty,
[Prd_Code]: value,
}));
}
};
const toggleDetails = (Prd_Code: string) => {
setExpandedProduct((prev) => (prev === Prd_Code ? null : Prd_Code));
};
const calculateTotalPrice = () => {
return products.reduce((total, product) => {
const quantity = qty[product.Prd_Code] || 0;
const saleRate = product.Sale_Rate || 0;
const gstp = product.Gst_Perc || 0;
return total + (saleRate * quantity + (saleRate * quantity) * gstp / 100);
}, 0);
};
return (
<Container>
<Paper style={{ padding: 20 }}>
<Typography variant="h4" align="center" gutterBottom>
Product Descriptions
</Typography>
<List>
{products.map((product, index) => (
<ListItem key={index}>
<Typography
variant="body1"
style={{
width: "100%",
backgroundColor: "#f9f9f9",
borderRadius: "10px",
padding: "10px",
}}
>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<div style={{ lineHeight: "0.3" }}>
<p className="code">{product.Prd_Code}</p>
<p className="descr">{product.Descr}</p>
</div>
<div style={{ paddingRight: "5px" }}>
{qty[product.Prd_Code] ? (
<div style={{ display: "flex", alignItems: "center" }}>
<IconButton
size="small"
onClick={() =>
handleDecreaseQuantity(product.Prd_Code)
}
>
<DeleteIcon fontSize="inherit" />
</IconButton>
<TextField
type="number"
value={qty[product.Prd_Code] || 0} // Display quantity or 0 if undefined
onChange={(event: any) => handleQuantityChange(event, product.Prd_Code)}
inputProps={{ min: 1 }}
style={{ width: "70px", margin: "0 10px" }}
InputProps={{
style: {
height: "30px", // Adjust the height if needed
// padding: "0 5px",
fontSize: "14px", // Set the font size for the input value
textAlign: "center", // Center the text inside the input
},
}}
InputLabelProps={{
style: {
fontSize: "0.9rem",
},
}}
/>
<IconButton
size="small"
onClick={() =>
handleIncreaseQuantity(product.Prd_Code)
}
>
<Add fontSize="inherit" />
</IconButton>
</div>
) : (
<Button
variant="contained"
color="primary"
style={{ background: "#2FD000", height: "30px" }}
onClick={() => handleAddToQty(product.Prd_Code)}
>
<AddShoppingCartIcon />
Add
</Button>
)}
</div>
</div>
<div
style={{
display: "flex",
justifyContent: "space-between",
marginTop: "10px",
}}
>
<Button
variant="contained"
size="small"
color="info"
onClick={() => toggleDetails(product.Prd_Code)}
>
{expandedProduct === product.Prd_Code
? "Hide Details"
: "Show Details"}
</Button>
{qty[product.Prd_Code] && (
<Typography
variant="body2"
style={{ color: "green" }}
>
PRODUCT NET VALUE:{" "}
{(qty[product.Prd_Code] * product.Sale_Rate + (qty[product.Prd_Code] * product.Sale_Rate) * product.Gst_Perc / 100).toFixed(2)}{" "}
<span>₹</span>
</Typography>
)}
</div>
{expandedProduct === product.Prd_Code && (
<div>
<table
border={1}
width={"100%"}
style={{ marginTop: "10px" }}
>
<tbody>
<tr>
<td className="heading">Company Name</td>
<td className="table_value">
{product.Company_Name}
</td>
<td className="heading">GST %</td>
<td className="table_value">
{product.Gst_Perc}
<span>%</span>
</td>
</tr>
<tr>
<td className="heading">MRP</td>
<td className="table_value">
<span>₹</span>
{product.Max_Rate}
</td>
<td className="heading">Sale Price</td>
<td className="table_value">
<span>₹</span>
{product.Sale_Rate}
</td>
</tr>
{product.Batch_No && (
<tr>
<td className="heading">Batch No</td>
<td className="table_value">{product.Batch_No}</td>
</tr>
)}
{product.Expiry && product.Expiry.trim() !== "-" && (
<tr>
<td className="heading">Expiry</td>
<td className="table_value">{product.Expiry}</td>
</tr>
)}
</tbody>
</table>
</div>
)}
</Typography>
</ListItem>
))}
</List>
<Typography
variant="h6"
style={{ marginTop: "20px", textAlign: "right", color: "blue" }}
>
Total Qty Price: <span>₹</span>
{calculateTotalPrice().toFixed(2)}
</Typography>
</Paper>
</Container>
);
};
export default ProductList;
Thanks for helping.
Sunrut Mevawala is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
The lag in your React component buttons may be due to the large amount of data being processed and rendered. Here are some options:
- Use React’s memo to avoid unnecessary re-renders
- Use “key” prop effectively (underrated)
- Also you could find a way to render only the visual content (like lazy loading)