Search code examples
javascriptreactjstypescriptreact-typescript

How to generate a nested ul from a flat array of objects


i have an array of objects:

const data = [
    {id: "0"},{id: "1"},{id: "2"},{id: "00"},{id: "01"},{id: "02"},{id: "11"},{id: "20"},{id: "23"},{id: "000"}{id: "013"}{id: "025"}{id: "026"}{id: "110"}{id: "111"}
]

My expected output:

<ul>
    <li>0
        <ul>
            <li>00
                 <ul>
                      <li>000</li>
                 </ul>
            </li>
            <li>01
                 <ul>
                      <li>013</li>
                 </ul>
            </li>
            <li>02
                 <ul>
                      <li>025</li>
                      <li>026</li>
                 </ul>
            </li>
        </ul>
    </li>
    <li>1
        <ul>
            <li>11
                 <ul>
                      <li>110</li>
                      <li>111</li>
                 </ul>
            </li>
        </ul>
    </li>
    <li>2
        <ul>
            <li>20</li>
            <li>23</li>
        </ul>
    </li>
   <li>3</li>
</ul>

My code so far:

export const NestedList = ({data, level = 1, parent = "0"}) => {
    return data
        .filter((item:any) => item.id.length === level)
        .map((item:any,i:number) => (
            <li key={i}>{item.id}{item.id.length < 3 && (
                <ul><NestedList data={data.filter((item: any) => item.id.length > level)} level={item.id.length + 1} parent={item.id.slice(0, item.id.length)} /></ul>
            )}</li>
        ));
}

Trying to add a condition to the filter such as level > 1 && item.id.slice(0, item.id.length -1) === parent doesn't work for me :( anyone have a clue?


Solution

  • In the filter you can add condition to select only the items which id starts with the parent id value and the level is the same as current level. PS I removed types for this snippet.

    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div id="root"></div>
    
     <script type="text/babel">
    
    const data=[{id:"0"},{id:"1"},{id:"2"},{id:"3"},{id:"00"},{id:"01"},{id:"02"},{id:"11"},{id:"20"},{id:"23"},{id:"000"},{id:"013"},{id:"025"},{id:"026"},{id:"110"},{id:"111"}];
    
    const NestedList = ({ data, level = 1, parent = "" }) => {
      return (
    <ul>
      {data
        .filter((item) => item.id.slice(0, -1) === parent && item.id.length === level)
        .map((item) => (
          <li key={item.id}>
            {item.id}
            {item.id.length < 3 && (
              <NestedList data={data} level={level + 1} parent={item.id} />
            )}
          </li>
        ))}
    </ul>
      );
    };
    
    ReactDOM.render(
      <NestedList data={data} />,
      document.getElementById("root")
    );
      
     </script>