I have been working on a webapp which can be used to store collections, there is a dashboard page where all the collections the user can see are shown in a table where each row is a collection and the columns are used to show collection name and a delete button.
This is the collecitonRow.tsx file:
"use client";
import React from "react";
import { useSession } from "next-auth/react";
type TableRow = {
id: string;
name: string;
};
type Props = {
row: TableRow;
className?: string;
};
const DEFAULT_ROW: TableRow = {
id: "0",
name: "Collection",
};
const CollectionRow = ({ row = DEFAULT_ROW, className }: Props) => {
const handleDeleteCollection = async () => {
console.log(row.id);
};
return (
<tr key={row.id}>
<td className={className}>
<div className="flex flex-col">
<p className="text-sm">{row.name}</p>
</div>
</td>
<td className={className}>
<button
onClick={() => (document.getElementById("delete") as any).showModal()}
className="btn btn-primary btn-sm"
>
</button>
<dialog id="delete" className="modal">
<div className="modal-box">
<h3 className="font-bold text-lg">Delete Collection?</h3>
<div className="modal-action">
<form method="dialog">
<button className="btn btn-primary">Close</button>
</form>
<button onClick={handleDeleteCollection}>
Delete
</button>
</div>
</div>
</dialog>
</td>
</tr>
);
};
export default CollectionRow;
And here’s the page.tsx where this component is used:
import React from "react";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth_options";
import CollectionRow from "@/components/collectionRow";
import AddCollection from "@/components/addCollection";
const TABLE_HEAD = [
"Name",
"Delete",
];
type TableRow = {
id: string;
name: string;
};
export default async function page() {
// Api request to fetch all rows
const tableRows: TableRow[] = (await res.json()) || [];
return (
<div>
<div className="h-full w-full bg-base-200">
<div className="px-0 overflow-auto ">
<table className="mt-2 w-full min-w-max table-auto text-left">
<thead>
<tr>
{TABLE_HEAD.map((head, index) => (
<th
key={head}
className="cursor-pointer border-y border-primary p-4"
>
<p className="text-sm flex items-center justify-between gap-2">
{head} {index !== TABLE_HEAD.length - 1}
</p>
</th>
))}
</tr>
</thead>
<tbody>
{tableRows.map((row: TableRow, index) => {
const isLast = index === tableRows.length - 1;
const classes = isLast ? "p-4" : "p-4 border-b border-primary ";
return (
<CollectionRow key={index} row={row} className={classes} />
);
})}
</tbody>
</table>
</div>
</div>
</div>
);
}
My problem is that in handleDeleteCollection i log the row.id but for some reason, whatever row the button is from, the id I get is always the one of the first row. I wanted to use that id to delete the row but i just can’t get it.
I tried editing collectionRow.tsx this way:
"use client";
import React from "react";
import { useSession } from "next-auth/react";
type TableRow = {
id: string;
name: string;
};
type Props = {
row: TableRow;
className?: string;
};
const DEFAULT_ROW: TableRow = {
id: "0",
name: "Collection",
};
const CollectionRow = ({ row = DEFAULT_ROW, className }: Props) => {
const handleDeleteCollection = async (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
console.log(e.target);
};
return (
<tr key={row.id}>
<td className={className}>
<div className="flex flex-col">
<p className="text-sm">{row.name}</p>
</div>
</td>
<td className={className}>
<button
onClick={() => (document.getElementById("delete") as any).showModal()}
className="btn btn-primary btn-sm"
>
</button>
<dialog id="delete" className="modal">
<div className="modal-box">
<h3 className="font-bold text-lg">Delete Collection?</h3>
<div className="modal-action">
<form method="dialog">
<button className="btn btn-primary">Close</button>
</form>
<button onClick={handleDeleteCollection} id={row.id}>
Delete
</button>
</div>
</div>
</dialog>
</td>
</tr>
);
};
export default CollectionRow;
to log all the button information, id included and it is still the first row’s id.
The weird thing is that all the other information (i only put the name to keep the code clean but there are a lot more in my code) is shown correctly, the only one giving problems is the id. I also tried printing it in page.tsx but there it appears to be correct. I have no idea what i’m doing wrong.
Can anyone please help me? Thanks
2
Answers
This is happening because all your buttons are calling the same dialog to open.
To fix this in your code you should specify a distinct id for each dialog and call the good one each time you click on a button to open it:
and give this specific id to your modal :
You are displaying a
td
element for each one, and you want the modal to open whenever a button is clicked:The problem here is that your modal, or
dialog
, rather has theid
ofdelete
for ALL of the rows that is mapped. This is not good. Theid
should be unique in the entireDOM
, not just in the component.Try to declare the
id
as such:And then the button: