I'm trying to make a table like this:
| --------
| - <Tr>
| <Tr>
| - <Tr>
| - <Tr>
| - <Tr>
| <Tr>
| <Tr>
| <Tr>
| <Tr>
| <Tr>
Table elements can contain thousands of child dropdown elements.
I am writing code in React and so far I have no idea and have not figured out how it can be done in a more optimized way.
Right now I am trying to work with a data structure like this
[
{
id: 1,
childrens: [
{ id: 10, childrens: [] },
{ id: 11, childrens: [{ id: 12, childrens: [] }] },
],
},
{ id: 2, childrens: [] },
];
Current implementation idea:
When I click on the dropdown element, I do the following:
- Get id
- I am looking for an element in the array by id
- I get the contents of
childrens
, if the array contains data, then I add them after the parent<tr>
element
To hide the dropdown <tr>
I do the following:
- Get id
- I am looking for an element in the array by id
- Get the length of the array
childrens
- I delete after the parent
<tr
element, the number of child<tr
is equal to the length of the array
But I don't understand how I can work with nested child elements. I need to somehow understand who is the parent of whom in order not to bypass the entire array again.
In what direction should I explore this issue?
CodePudding user response:
I had to do this once and solved it using recursion. Create your table and loop over the first layer of data.
const TableDropdown = ({ data }) => {
return (
<table>
<tbody>
// loop over the first layer of data
{data.map((row) => (
<DropdownRow key={`dropdown-row-${row.id}`} row={row} />
))}
</tbody>
</table>
);
};
For the implementation of the row
- In the row we set a state to keep track of the open state.
- Define a toggle function to toggle between open and closed.
- Finally determine whether or not we have children and check if the dropdown is open.
const DropdownRow = ({ row }) => {
const [isOpen, setIsOpen] = useState(false);
// check whether the row has children
const hasChildren = row.childrens.length > 0;
// toggle the row
const toggleRow = () => {
// no need to toggle if no children
if (!hasChildren) return;
setIsOpen((prev) => !prev);
};
// create the child rows if the current row has children and is opened
const childRows =
hasChildren && isOpen
? row.childrens.map((childRow) => (
<DropdownRow key={`dropdown-row-${childRow.id}`} row={childRow} />
))
: null;
// just to determine which "icon" to display
const toggleIcon = !hasChildren ? "=" : isOpen ? "-" : " ";
return (
<>
<tr>
<td onClick={toggleRow}>{toggleIcon}</td>
<td>Row with id {row.id}</td>
</tr>
{childRows}
</>
);
};
Check here for a live version