Reputation: 265
I have two mapped lists of items. When I click on the div
using onClick={(e) => handleCheckClick(ele)}
I want to display the clicked items in a table but I am getting errors.
handleCheckClick
function
function handleCheckClick(ele) {
if (trayItems?.length > 0) {
settrayItems(
trayItems.map((item) => {
return { ...item, quantity: item.quantity + 1 };
})
);
} else {
settrayItems([...trayItems, ele]);
}
}
How I map two list items into div
<div>
{
item && item.filter((person) => person.status == "0").map((ele) => {
return (
<div
className="newmo-card"
style={styles.innerbox}
onClick={(e) => handleCheckClick(ele)}>
{`${ele.item}`}
<br />
<span> {`${ele.total_price}`}</span>
</div>
);
})
}
</div>
<Tray trayItems2={trayItems} trayItems1={trayPrice} />
Table of clicked items:
function Tray({ trayItems }) {
return (
<>
<div className="foo">
<table>
{trayItems &&
trayItems.map((ele, index) => {
return (
<tr key={index}>
<td>{ele.item}</td>
<td>{ele.price}</td>
<td>{ele.quantity}</td>
</tr>
</table>
</div>
</>
);
}
Check the sandbox so you can identify the issue
Upvotes: 2
Views: 332
Reputation: 188
The (find) method was added to compare the id with the trayItems array, >using the selection id, inside with the (map) method, we validate again >using ternary, if it is equal it increases, if not, it is the same, now yes >selected value is not found, create a new one and add element quantity = 1
method (map) was created inside to validate the selection using the >ternary is subtracted, valid up to 1, but if we click again, we delete it, >the button for the decre() function is activated by ele.quantity
https://codesandbox.io/s/fast-currying-nfmxfm?file=/src/App.js
export default function App() {
const [trayItems, settrayItems] = useState([]);
// 1.
const handleCheckClick = (ele) => {
const dupe = trayItems.find((obj) => obj.user_id === ele.user_id);
settrayItems(
dupe
? trayItems.map((stat) =>
stat.user_id === ele.user_id
? { ...stat, quantity: stat.quantity + 1 }
: stat
)
: [...trayItems, { ...ele, quantity: (ele.quantity = 1) }]
);
};
// 2.
const decre = (idd) => {
settrayItems(
trayItems.map((stat) =>
stat.user_id === idd
? stat.quantity !== 1
? {
...stat,
quantity:
stat.quantity > 1 ? stat.quantity - 1 : (stat.quantity = 1)
}
: trayItems.filter((e) => e.id !== idd)
: stat
)
);
};
function Tray({ trayItems }) {
return (
<>
<div className="foo">
<table>
<tbody>
{trayItems &&
trayItems.map((ele, index) => {
return (
<tr key={index}>
<td>{ele.item}</td>
<td>{ele.price}</td>
<td onClick={() => decre(ele.user_id)>{ele.quantity}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</>
);
}
return (
<>
<div>
{item &&
item
.filter((person) => person.status === 0)
.map((ele, index) => {
return (
<div
style={{ cursor: "pointer" }}
key={index}
className="newmo-card"
onClick={() => handleCheckClick(ele)}
>
{`${ele.item}`}
<br />
<br />
<span> {`${ele.price}`}</span>
</div>
);
})}
</div>
<Tray trayItems={trayItems} />
</>
);
}
Upvotes: 0
Reputation: 535
There is something issue that in your code
handleCheckClick
function
const handleCheckClick = (ele) => {
let index = trayItems.findIndex((item) => item.user_id === ele.user_id);
if (index >= 0) {
let newItems = trayItems;
let item = trayItems.find((item) => item.user_id === ele.user_id);
item = { ...item, quantity: item.quantity + 1 };
newItems.splice(index, 1, item);
settrayItems([...newItems]);
} else {
settrayItems([...trayItems, ele]);
}
};
For more details Check the sandbox
Upvotes: 0
Reputation: 121
The issue in your code was how you handled the click function and the modification of state subsequently.
const items = [
{
user_id: 1,
item: "biriani",
price: "50",
selling_price: "60",
created_at: "2022-08-29T10:12:58.000000Z",
updated_at: "2022-09-15T14:05:45.000000Z",
tax: "5%",
total_price: "80",
status: 0,
quantity: 0
},
{
user_id: 2,
item: "burger",
price: "80",
selling_price: "80",
created_at: "2022-08-29T10:21:13.000000Z",
updated_at: "2022-09-14T04:46:36.000000Z",
tax: "5%",
total_price: "100",
status: 0,
quantity: 0
},
{
user_id: 3,
item: "alfarm",
price: "100",
selling_price: "120",
created_at: "2022-09-07T11:06:23.000000Z",
updated_at: "2022-09-07T11:06:23.000000Z",
tax: "5%",
total_price: "140",
status: 0,
quantity: 0
},
{
user_id: 4,
item: "sandwich",
price: "100",
selling_price: "120",
created_at: "2022-09-07T13:27:33.000000Z",
updated_at: "2022-09-14T04:46:37.000000Z",
tax: "5",
total_price: "140",
status: 0,
quantity: 0
},
{
user_id: 5,
item: "pizza",
price: "200",
selling_price: "220",
created_at: "2022-09-07T13:27:33.000000Z",
updated_at: "2022-09-07T13:27:33.000000Z",
tax: "5",
total_price: "240",
status: 0,
quantity: 0
},
{
user_id: 6,
item: "chicken sadwich",
price: "200",
selling_price: "220",
created_at: "2022-09-07T13:27:33.000000Z",
updated_at: "2022-09-07T13:27:33.000000Z",
tax: "5",
total_price: "250",
status: 0,
quantity: 0
},
{
user_id: 7,
item: "sharja shake",
price: "60",
selling_price: "70",
created_at: "2022-09-09T06:58:45.000000Z",
updated_at: "2022-09-15T14:05:53.000000Z",
tax: "5%",
total_price: "80",
status: 0,
quantity: 0
}
];
export default function App() {
const [trayItems, setTrayItems] = useState([]);
const handleCheckClick = (item) => {
const itemExists = trayItems.findIndex((ite) => ite.user_id === item.user_id) !== -1;
if (itemExists) {
setTrayItems(
trayItems.map((prod) => ({
...prod,
quantity:
prod.user_id === item.user_id ? prod.quantity + 1 : prod.quantity
}))
);
} else {
setTrayItems([...trayItems, { ...item, quantity: item.quantity + 1 }]);
}
};
return (
<>
<table>
{items
?.filter((item) => item.status === 0)
?.map((item, index) => {
return (
<tbody
key={index}
onClick={() => handleCheckClick(item)}
>
<td>{item.item}</td>
<td>{item.total_price}</td>
</tbody>
);
})}
</table>
<Tray trayItems={trayItems} />
</>
);
}
const Tray = ({ trayItems }) => {
return (
<table>
<tbody>
{trayItems?.map((ele, index) => (
<tr key={index}>
<td>{ele.item}</td>
<td>{ele.price}</td>
<td>{ele.quantity}</td>
</tr>
))}
</tbody>
</table>
);
};
Upvotes: 0
Reputation: 4474
I'm sharing the significant parts of the code here. Check the code sandbox for the working code.
Here are the significant changes:
Tray
definition outside the App
component. Defining a component inside another component is almost always a bad idea. You won't have an issue because you don't have any state in Tray
. If you had any state, it would have been reset to the initial value on every render of App
.trayItems
to an object. The keys are the id
s of each item. And the value is an object that contains the name, quantity, and price.Tray
if the quantity is greater than 0
.handleCheckClick
to handle the object.function Tray({ trayItems }) {
return (
<>
<div className="foo">
<table>
<tbody>
{Object.entries(trayItems)
.filter(([, v]) => v.quantity > 0)
.map(([k, v]) => {
return (
<tr key={k}>
<td>{v.item}</td>
<td>{v.price}</td>
<td>{v.quantity}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</>
);
}
export default function App() {
const [trayItems, setTrayItems] = useState(
item.reduce((prev, curr) => {
return {
...prev,
[curr.user_id]: { item: curr.item, quantity: 0, price: curr.price }
};
}, {})
);
const handleCheckClick = (ele) => {
setTrayItems((prev) => {
return {
...prev,
[ele.user_id]: {
...prev[ele.user_id],
quantity: prev[ele.user_id].quantity + 1
}
};
});
};
return (
<>
<div>
{item &&
item
.filter((person) => person.status === 0)
.map((ele, index) => {
return (
<div
key={index}
className="newmo-card"
onClick={() => handleCheckClick(ele)}
>
{`${ele.item}`}
<br />
<span> {`${ele.total_price}`}</span>
</div>
);
})}
</div>
<Tray trayItems={trayItems} />
</>
);
Upvotes: 1
Reputation: 697
here why do you manage two diff states? pls check the working demo here.
import { Fragment, useState } from "react";
import "./styles.css";
const item = [
{
user_id: 1,
item: "biriani",
price: "50",
selling_price: "60",
created_at: "2022-08-29T10:12:58.000000Z",
updated_at: "2022-09-15T06:17:20.000000Z",
tax: "5%",
total_price: "80",
status: 1,
quantity: 0
},
{
user_id: 5,
item: "alfarm",
price: "100",
selling_price: "120",
created_at: "2022-09-07T11:06:23.000000Z",
updated_at: "2022-09-07T11:06:23.000000Z",
tax: "5%",
total_price: "140",
status: 0,
quantity: 0
}
];
export default function App() {
const [trayItems, settrayItems] = useState([]);
const handleCheckClick = (ele) => {
if (trayItems?.length > 0) {
settrayItems(trayItems.map((item) => {
return { ...item, quantity: item.quantity + 1 };
}))
} else {
settrayItems([...trayItems, ele]);
}
};
function Tray({ trayItems }) {
return (
<>
<div className="foo">
<table>
<tbody>
{trayItems &&
trayItems.map((ele, index) => {
return (
<tr key={index}>
<td>{ele.item}</td>
<td>{ele.price}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</>
);
}
return (
<>
<div>
{item &&
item
.filter((person) => person.status === 0)
.map((ele, index) => {
return (
<div
key={index}
className="newmo-card"
onClick={() => handleCheckClick(ele)}
>
{`${ele.item}`}
<br />
<span> {`${ele.total_price}`}</span>
</div>
);
})}
</div>
<Tray trayItems={trayItems} />
</>
);
}
Upvotes: 0
Reputation: 449
There is a warning that <td> and <tr> cannot appear as a child of <table>
.
Wrap body with <body>
tag and use <tr>
tag to represent each row.
<div className="foo">
<table>
<tbody>
{trayItems2.length === trayItems1.length &&
trayItems2.map((ele, index) => {
return (
<tr key={ele}>
<td>{ele}</td>
<td>{trayItems1[index]}</td>
</tr>
);
})}
</tbody>
</table>
</div>
Because of using trayItems1[index]
to get map items in another array so you need to pre-check them. You need to refine it for tighter conditions.
Also, define unique key props for each child element in <table>
. Here I simply use key={ele}
. And using two arrays is redundant. Merge them could be easier.
Upvotes: 0