2

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:

  1. Get id
  2. I am looking for an element in the array by id
  3. 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:

  1. Get id
  2. I am looking for an element in the array by id
  3. Get the length of the array childrens
  4. 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?

1 Answer 1

1

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

  1. In the row we set a state to keep track of the open state.
  2. Define a toggle function to toggle between open and closed.
  3. 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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.