Создать дерево JSX из плоского массива с рекурсивной функцией в React - PullRequest
1 голос
/ 29 мая 2020

Мне действительно нужна ваша помощь, чтобы создать дерево JSX из плоского массива в реакции с использованием рекурсивной функции.

На данный момент правильно отображаются только элементы с 1 по 6, и рекурсия останавливается после

My falt array look like that

My aim is to create this JSX tree related to the level

1) мои плоские JSON данные: (но в нем может быть более 1000 элементов)

const itemsData = [
{
  "Level": 1,
  "Type of activity": "Consolidated task",
  "ID": 118027222233,
  "Name": "Name 1"
},
{
  "Level": 2,
  "Type of activity": "Consolidated task",
  "ID": 118636886633,
  "Name": "Name 2"
},
{
  "Level": 3,
  "Type of activity": "Consolidated task",
  "ID": 118637048333,
  "Name": "Name 3"
},
{
  "Level": 4,
  "Type of activity": "task",
  "ID": 118637035433,
  "Name": "Name 4"
},
{
  "Level": 4,
  "Type of activity": "task",
  "ID": 118841127933,
  "Name": "Name 5"
},
{
  "Level": 4,
  "Type of activity": "task",
  "ID": 118841156833,
  "Name": "Name 6"
},
{
  "Level": 3,
  "Type of activity": "Consolidated task",
  "ID": 118637046733,
  "Name": "Name 9"
},
{
  "Level": 4,
  "Type of activity": "Consolidated task",
  "ID": 118744514633,
  "Name": "Name 10"
},
{
  "Level": 5,
  "Type of activity": "task",
  "ID": 118637033033,
  "Name": "Name 11"
},
{
  "Level": 5,
  "Type of activity": "task",
  "ID": 118637031033,
  "Name": "Name 13"
},
{
  "Level": 2,
  "Type of activity": "Consolidated task",
  "ID": 118636886633,
  "Name": "Name 19"
},
{
  "Level": 3,
  "Type of activity": "task",
  "ID": 118637048333,
  "Name": "Name 20"
},
{
  "Level": 3,
  "Type of activity": "task",
  "ID": 118637048333,
  "Name": "Name 21"
}]

2) Моя текущая рекурсивная функция выглядит так: Но правильно отображаются только элементы с 1 по 6.

const RecursiveFunction = ({currentItem, currentLevel}) => {

//LOOP  AS LONG AS CURRENTITEM < ITEMS DATA LENGTH 
while(currentItem < itemsData.length){

    //IF CONSOLODATED TASK CREATE CONTAINER
    if(itemsData[currentItem]["Type of activity"] === "Consolidated task"){


        //TEST IF CHILD RELATED TO LEVEL
        if(currentLevel < itemsData[currentItem].Level ){


            //LINE COUNTER
            currentItem++;

            //RETURN
            return (
                <div className="conso-container">
                    <div className="conso-title">
                        {itemsData[currentItem - 1].Name}
                    </div>
                    <RecursiveFunction currentItem={currentItem} currentLevel={itemsData[currentItem-1].Level} />
                </div>
            )
        }

    }else{

        //CURRENT TASK LIST ON A BLOCK
        let taskList = [];

        //WHILE IS A TASK
        while(currentItem < itemsData.length && itemsData[currentItem]["Type of activity"] !== "Consolidated task"){

            //LIST ALL THE TASK
            taskList.push(<div className="task-title">{itemsData[currentItem].Name}</div>)
            currentItem++;

        }

        // RETURN    
        return (
            <div className="task-container">
                {taskList}
            </div>
        )
    }
}}

3) Мой рендер

class RoadMapItems extends React.Component {


render(){
    return( 
        <div className="tree">
            <RecursiveFunction currentItem={0} currentLevel={0} />
        </div>
    )
}}export default RoadMapItems;

1 Ответ

0 голосов
/ 29 мая 2020

Это должно работать. Это было немного сложнее, чем я думал изначально, ха-ха. ?

Вам нужно преобразовать во вложенную структуру данных, а затем рекурсивно отобразить ее, чтобы получить желаемый результат:

Полная демонстрация ниже и здесь: https://codepen.io/Alexander9111/pen/pojXBWX

function MyTable(props) {
  const initState = [
    {
      Level: 1,
      "Type of activity": "Consolidated task",
      ID: 118027222233,
      Name: "Name 1"
    },
    {
      Level: 2,
      "Type of activity": "Consolidated task",
      ID: 118636886633,
      Name: "Name 2"
    },
    {
      Level: 3,
      "Type of activity": "Consolidated task",
      ID: 118637048333,
      Name: "Name 3"
    },
    {
      Level: 4,
      "Type of activity": "task",
      ID: 118637035433,
      Name: "Name 4"
    },
    {
      Level: 4,
      "Type of activity": "task",
      ID: 118841127933,
      Name: "Name 5"
    },
    {
      Level: 4,
      "Type of activity": "task",
      ID: 118841156833,
      Name: "Name 6"
    },
    {
      Level: 3,
      "Type of activity": "Consolidated task",
      ID: 118637046733,
      Name: "Name 9"
    },
    {
      Level: 4,
      "Type of activity": "Consolidated task",
      ID: 118744514633,
      Name: "Name 10"
    },
    {
      Level: 5,
      "Type of activity": "task",
      ID: 118637033033,
      Name: "Name 11"
    },
    {
      Level: 5,
      "Type of activity": "task",
      ID: 118637031033,
      Name: "Name 13"
    },
    {
      Level: 2,
      "Type of activity": "Consolidated task",
      ID: 118636886633,
      Name: "Name 19"
    },
    {
      Level: 3,
      "Type of activity": "task",
      ID: 118637048333,
      Name: "Name 20"
    },
    {
      Level: 3,
      "Type of activity": "task",
      ID: 118637048333,
      Name: "Name 21"
    },
    {
      Level: 2,
      "Type of activity": "Consolidated task",
      ID: 128637048333,
      Name: "Name 22"
    },
    {
      Level: 3,
      "Type of activity": "task",
      ID: 138637048333,
      Name: "Name 23"
    },
    {
      Level: 1,
      "Type of activity": "Consolidated task",
      ID: 148637048333,
      Name: "Name 24"
    },
    {
      Level: 2,
      "Type of activity": "task",
      ID: 158637048333,
      Name: "Name 25"
    }
  ];
  const [state, setState] = React.useState(initState);

  const table = (
    <table>
      <tr key={"header"}>
        {Object.keys(state[0]).map((key) => (
          <th>{key}</th>
        ))}
      </tr>
      {state.map((item) => (
        <tr key={item.id}>
          {Object.values(item).map((val) => (
            <td>{val}</td>
          ))}
        </tr>
      ))}
    </table>
  );

  let currPointer = null;
  const listOfPointers = [];
  const nestedArrs = state.reduce((aggArr, item) => {
    //console.log(listOfPointers)
    if (item.Level == 1) {
      aggArr.push(item);
    }
    else if (item.Level > currPointer.Level) {
      currPointer.children.push(item);
    }
    else if (item.Level <= currPointer.Level) {
      while (item.Level <= currPointer.Level) {
        listOfPointers.pop();
        currPointer = listOfPointers[listOfPointers.length - 1];
      }
      currPointer.children.push(item);
    }
    
    item.children = [];
    currPointer = item;
    listOfPointers.push(currPointer);

    return aggArr;
  }, []);

  //console.log(nestedArrs);

  const nestedDivs = (
    <div>
      {(function mapChildren(data) {
        return data.map((d, i) => {
          if (d["Type of activity"] != "task") {
            return (
              <div className={"level_" + d.Level}>
                <span>{d.Level + " : " + d.Name}</span>
                {mapChildren(d.children)}
              </div>
            );
          } else {
            return (
              <div className={"level_" + d.Level + " task"}>
                <span>{d.Level + " : " + d.Name}</span>
              </div>
            );
          }
        });
      })(nestedArrs)}
    </div>
  );
  //console.log(nestedDivs);

  return (
    <div>
      {table}
      {nestedDivs}
    </div>
  );
}

ReactDOM.render(<MyTable />, document.getElementById("target"));
th,
td {
  border: 1px solid black;
  margin: 0px 0px;
  padding: 5px 5px;
}
div {
  padding: 10px;
  margin: 10px;
}
.level_1 {
  background-color: blue;
}
.level_2 {
  background-color: orange;
}
.level_3 {
  background-color: green;
}
.level_4 {
  background-color: yellow;
}
.task {
  background-color: white !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="target"></div>

Ввод:

enter image description here

Выход:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...