以递归方式渲染React组件

时间:2018-01-04 16:07:24

标签: javascript reactjs recursion react-redux nested-sets

我有一个对象数组,需要递归渲染每个单独的对象,如未标记的列表:

<ul>
   <li>
   </li>
</ul>

所有数据都来自服务器,如简单的JSON:

{
        "Id": 1,
        "Description": "asd",
        "Src": " ",
        "Lft": 0,
        "Rgt": 9
    },
    {
        "Id": 2,
        "Description": "asd2",
        "Src": " ",
        "Lft": 1,
        "Rgt": 2
    },
    {
        "Id": 3,
        "Description": "asd3",
        "Src": " ",
        "Lft": 3,
        "Rgt": 8
    },
    {
        "Id": 4,
        "Description": "asd4",
        "Src": " ",
        "Lft": 4,
        "Rgt": 5
    },
    {
        "Id": 5,
        "Description": "asd5",
        "Src": " ",
        "Lft": 6,
        "Rgt": 7
    }

我正在使用嵌套集模型进行添加和删除。添加/删除是正常的,添加新元素生成并重新计算正确的键(删除相同的确定) 我也可以渲染所有项目(在我的例子中是一行)。但目标是使其视图分层。 这是一个例子我如何渲染lft | rgt(但我使用的是常用的JS)

enter image description here

要渲染我使用下一个函数( function renderItems(items )):

    renderItems(items) {
    let node = document.getElementById('root');
    node.innerHTML = '';
    if (items.length) {
        var ul = document.createElement('ul');
        var tree = fetchChildElement(ul);
        node.appendChild(tree);
    }
    function fetchChildElement(container, lft, rgt) {
        items.filter(filterItems); //go through data array
        return container;

        function filterItems(item) {
            if (item.Lft === (lft || 0)) {
                var element = document.createElement('li');
                element.innerHTML = (item.Lft + " | " + item.Rgt);

                //check if element got nested elements, if true - call function again
                if (item.Lft + 1 < item.Rgt) {
                    var childContainer = document.createElement('ul');
                    var child = fetchChildElement(childContainer, item.Lft + 1, item.Rgt - 1);
                    element.appendChild(child);
                }

                //add element to container
                container.appendChild(element);

                //check if next element exists and call function for them
                if (rgt && item.Rgt < rgt) {
                    fetchChildElement(container, item.Rgt + 1, rgt);
                }
            }
        }
    }
}

这是我的组件: 的 Item.js

class Item extends Component {

render() {
    let { item, showModalPlusClicked, deleteItem } = this.props

    return (
        <li className="item">     
                {item.Description &&
                    <div>
                        <img src={item.Src} alt="" />
                        {"Description: " + item.Description}
                        <div className="buttons">
                            <button className="addBtn btn" onClick={(id) => showModalPlusClicked(item)}>+</button>
                            <button className="removeBtn btn" onClick={(id) => deleteItem(item.Id)}>-</button>
                        </div>
                        <p>lKey is {item.Lft} <span>|||| rKey is {item.Rgt}</span></p>
                        <p>______________________</p>
                        <p>id is {item.Id}</p>
                    </div>
                }   
        </li>

    )
}

}

这是我的 ItemList.js 组件,其中,我认为所有递归的magi应该是:

class ItemList extends Component {
render() {
        let { items, showModalPlusClicked, deleteItem } = this.props
        return ( 
            <div className='items'>
                <ul>
                    {items.map((item) =>
                        <Item
                            key={item.Id}
                            item={item}
                            src={item.Src}
                            desc={item.description}
                            lft={item.lft}
                            rgt={item.rgt}
                            showModalPlusClicked={showModalPlusClicked}
                            deleteItem={deleteItem}
                        />
                    )}
                </ul>
            </div>
        )
    }
}

下面是截图,它是如何使用正确风格化的项目(但不是层次结构)呈现的,还使用了display:inline-block in li.items以便更好地理解 enter image description here

顺便说一句,为了渲染第一张图片上的项目我只是将{this.renderItems(items)}传递给ItemList的render()方法。

所以,最后我认为最好恢复上述所有词语。

  • 我有一个对象数组ItemsList。
  • ItemList中的每个对象都是Item。
  • 每个项目都有2个主要标识符(leftKey - lft和rightKey - rgt),它们应该用于在无序列表中显示Item()。
  • 我有javascript函数可以获取这个键并在index.html中显示smth但是我不能理解如何重新制作它(或者可能是函数应该完全是另一个)
  • 另外,我将不同的数据传递给我的JS函数,它使得ul&gt; li正确,所以我认为所有的更改都应该在其中。
所以,我不知道如何以这种方式呈现我的反应组件Item的主要问题。

修改 '那样'我的意思是 - 项目组件呈现像无序列表(见第1张图片)。我的图像只有左右键,而不是它们应该有整个Item组件(如图2所示)

修改 有什么想法如何实现这个?我绝望了......

1 个答案:

答案 0 :(得分:0)

我在开发多线程聊天应用程序时遇到了同样的问题。 Demo

我设计了组件的css,这样当一个新的组件呈现它时,它会移动一点点来实现你想要的东西。 React Code

希望这会有所帮助。