JSFiddle - React, Tailwind, and code Playground

JavaScript

function Node(id, text) {
  	this.id = id;
    this.children = [];
    this.text = text;
  }
  
  Node.prototype.hasChildren = function () {
  	return this.children.length !== 0;
  }
  
  function connectNodes(fromNode, toNode) {
  	fromNode.children.push(toNode);
    toNode.parentNode = fromNode;
  }

	var list = [
	    {"id": 1, "parentId": null, "text": "Первая строка"}, 
	    {"id": 2, "parentId": 3,    "text": "Вторая строка"}, 
	    {"id": 3, "parentId": 1,    "text": "Третья строка"},
	    {"id": 4, "parentId": 1,    "text": "Четвёртая строка"},
	    {"id": 5, "parentId": null, "text": "Пятая строка"}, 
	    {"id": 6, "parentId": 5,    "text": "Шестая строка"}, 
	    {"id": 7, "parentId": 6,    "text": "Седьмая строка"}, 
	    {"id": 8, "parentId": 5,    "text": "Восьмая строка"}, 
	    {"id": 9, "parentId": 8,    "text": "Девятая строка"}, 
	    {"id": 10, "parentId": 4,   "text": "Десятая строка"}, 
	    {"id": 11, "parentId": 4,   "text": "Одиннадцатая строка"}, 
	];

/*
Список в виде дерева:

1--3--2
\
 4--10
 \
 11

5--6--7
\
 8-9

*/

	function mapListToTree(list) {
		var tree = [];
		list.forEach(row => {
			var node = tree.find(node => node.id === row.id);
			if (!node) {
				node = new Node(row.id, row.text);
				tree.push(node);
			}
			if (row.parentId) {
				var nodeInTree = tree.find(node => node.id === row.parentId);
				if (nodeInTree) {
					connectNodes(nodeInTree, node);
				} else {
					var parentNode = new Node(
						row.parentId,
						list.find(node => node.id === row.parentId).text
					);
					connectNodes(parentNode, node);
					tree.push(parentNode);
				}
			}
		});
		return tree;
	}

	var visitedNodes = [];
	function traverseTree(tree, depth = 0) {
		tree.forEach(node => {
			if (visitedNodes.indexOf(node) === -1) {
				visitedNodes.push(node);
			    console.log('-'.repeat(depth) + node.text);
				if (node.hasChildren()) {
					traverseTree(node.children, depth + 1);
				}
			}
		});
	}

	var tree =...