1

I have an array of objects whose schema is something like this.

[
  { text: 'Contents', level: 2 },
  { text: 'h2 Heading', level: 2 },
  { text: 'h3 Heading', level: 3 },
  { text: 'h4 Heading', level: 4 },
  { text: 'Heading', level: 2 },
]

I want to create an unordered list based on the levels of each object. So, for eg. the above array should be displayed as:

<ul>
    <li>Contents</li>
    <li>
        h2 Heading
        <ul>
            <li>
                h3 Heading
                <ul>
                    <li>h4 Heading</li>
                </ul>
            </li>
        </ul>
    </li>
    <li>Heading</li>
</ul>

I can check for the next object if it has the same level as the previous one. And handle the queries accordingly, but is there a better solution? Or any solution that works properly.

Edit #1: Just now, I found a solution that was asked here around 13 years ago. I can style the elements giving it a perception of a nested list. Link: Produce heading hierarchy as ordered list

Still, if there is a better solution, please do reply.

Aman Kumar
  • 29
  • 6

1 Answers1

0

This is a possible solution. You can check this link for a reactive online code editor.

const objects = [
  { text: "Contents", level: 2 },
  { text: "h2 Heading", level: 2 },
  { text: "h3 Heading", level: 3 },
  { text: "h4 Heading", level: 4 },
  { text: "Heading", level: 2 }
];

const getDisplayableObjects = () => {
  const arr = [];
  let targetArr;

  for (const obj of objects) {
    const { text, level } = obj;

    switch (level) {
      case 2:
        arr.push({ text, children: [] });
        break;
      case 3:
        targetArr = arr[arr.length - 1].children;
        targetArr.push({ text, children: [] });
        break;
      case 4:
        targetArr = arr[arr.length - 1].children;
        targetArr = targetArr[targetArr.length - 1].children;
        targetArr.push({ text, children: [] });
        break;
      default:
        break;
    }
  }

  return arr;
};

const App = () => {
  return (
    <>
      {getDisplayableObjects().map(({ text, children }) => (
        <ul>
          <li>
            {text}

            {children.map(({ text, children }) => (
              <ul>
                <li>{text}</li>

                {children.map(({ text, children }) => (
                  <ul>
                    <li>{text}</li>
                  </ul>
                ))}
              </ul>
            ))}
          </li>
        </ul>
      ))}
    </>
  );
};

export default App;

Result:

enter image description here

Tarek Hammami
  • 840
  • 9
  • 12
  • Hi, This solution works. Thanks for this. However, I'd use recursion instead of nesting those children. But anyway, this approach worked, and thanks for that again. – Aman Kumar Apr 01 '22 at 21:13