Javascript 递归树

Javascript 递归树,javascript,reactjs,tree,Javascript,Reactjs,Tree,我正在尝试使用ReactJS递归地呈现树结构。我很快就做了一个普通的例子(如下)。现在我正在移植它来做出反应,我已经看了一段时间了,但不知道如何做。我把我的React例子放在香草的下面 香草JS createTree(data, isSub, lev) { let level = lev || 0; let html = (isSub) ? '<div class="filter-body">' : ''; // Wrap with div if true if (isSub) {

我正在尝试使用ReactJS递归地呈现树结构。我很快就做了一个普通的例子(如下)。现在我正在移植它来做出反应,我已经看了一段时间了,但不知道如何做。我把我的React例子放在香草的下面

香草JS

createTree(data, isSub, lev) {
let level = lev || 0;
let html = (isSub) ? '<div class="filter-body">' : ''; // Wrap with div if true
if (isSub) { level++; }

for (let i = 0, len = data.length; i < len; i++) {
    if (typeof(data[i].nested_values) === 'object') {
        html += '<div class="filter-group level-' + level + '">';
        if (isSub) {
            html += '<div class="filter-heading">' + data[i].value + '</div>';
        } else { // Submenu found, but top level list item.
            html += '<div class="filter-heading">' + data[i].value + '</div>';
        }
        // Submenu found, call function recursively
        html += this.createTree(data[i].nested_values, true, level);
        html += '</div>';
    } else {
        html += '<span>' + data[i].value + '</span>' // No submenu, end of tree
    }

}
html += (isSub) ? '</div>' : '';
return html;

这与任何其他递归函数都没有区别。要使其工作,函数必须返回一些内容

这条线

{this.createTree(data[i].nested_values, true, level)} // How to do this properly?
表示将
this.createTree
的返回值作为子元素传递给元素。因为你的函数不返回任何东西,所以这不起作用

更正的示例:

createTree(data, isSub, lev) {
    let level = lev || 0;
    let children = [];
    for (let i in data) {
        if (typeof(data[i].nested_values) === 'object') { // Sub array found, build structure
            children.push(
                <div class={"filter-group level-" + (level)}>
                    <div class="filter-heading">{data[i].value}</div>
                    {this.createTree(data[i].nested_values, true, level)}
                </div>
            );
        } else { // No submenu, bottom of tree
            children.push(
                <span key={i}>
                    {data[i].value}               
                </span>
            );
        }
    }
    return <div className='filter-body open'>{children}</div>;
}
createTree(数据、发布、级别){
设标高=标高| | 0;
让孩子们=[];
for(让我输入数据){
如果(typeof(data[i].嵌套的_值)=='object'){//找到子数组,则生成结构
推(
{data[i].value}
{this.createTree(数据[i]。嵌套的_值,true,level)}
);
}else{//无子菜单,树的底部
推(
{data[i].value}
);
}
}
返回{children};
}

如果<代码>数据< /代码>是一个数组,请考虑使用它。

这取决于您想要的输出。将React元素添加到数组的事实使事情变得复杂。理想情况下,函数只返回一个元素。@FelixKling完全同意u。。他还可以利用道具的概念以及复合生命周期。之所以使用数组,是因为我希望嵌套的Togleable div prob有一个更好的方法——首先要让它工作refactor@FelixKling-如何将自定义对象传递给子组件。其想法是,在每个子级上,我希望它来自json中的路径,例如级别1-{value:“Fruit”}级别2-{value:“Fruit”,嵌套的_值:[{value:'热带'}]}级别3-{value:“Fruit”,嵌套的_值:[{value:'热带',嵌套的_值:[{value:'菠萝'}]}]我需要选择一个树元素,然后将它的整个结构(json)作为一个动作发送到Redux Store,我只是错过了返回!?嗯,
this.tmpArr
this.tmpArrB
的使用也是有问题的。啊,是的,我知道你做了什么!谢谢Felix,我回家后会试试这个。谢谢Felix,我对它进行了大量重构,现在觉得它看起来好多了,更新了我的答案。任何意见都将不胜感激!
{
    "possible_values": [{
        "value": "Fruit",
        "occurrence_count": 5,
        "nested_values": [{
            "value": "Berries",
            "occurrence_count": 3,
            "nested_values": [{
                "value": "Strawberry",
                "occurrence_count": 1
            }, {
                "value": "Blackberry",
                "occurrence_count": 1
            }, {
                "value": "Raspberry",
                "occurrence_count": 1
            }, {
                "value": "Redcurrant",
                "occurrence_count": 1
            }, {
                "value": "Blackcurrant",
                "occurrence_count": 1
            }, {
                "value": "Gooseberry",
                "occurrence_count": 1
            }, {
                "value": "Cranberry",
                "occurrence_count": 1
            }, {
                "value": "Whitecurrant",
                "occurrence_count": 1
            }, {
                "value": "Loganberry",
                "occurrence_count": 1
            }, {
                "value": "Strawberry",
                "occurrence_count": 1
            }]
        }, {
            "value": "Tropical",
            "occurrence_count": 2,
            "nested_values": [{
                "value": "Pineapple",
                "occurrence_count": 1
            }, {
                "value": "Mango",
                "occurrence_count": 1
            }, {
                "value": "Guava",
                "occurrence_count": 1
            }, {
                "value": "Passion Fruit",
                "occurrence_count": 1
            }, {
                "value": "Dragon Fruit",
                "occurrence_count": 1
            }]
        }]
    }, {
        "value": "Vegetable",
        "occurrence_count": 2,
        "nested_values": [{
            "value": "Potato",
            "occurrence_count": 3
        }, {
            "value": "Leek",
            "occurrence_count": 3
        }, {
            "value": "Onion",
            "occurrence_count": 3
        }, {
            "value": "Sprout",
            "occurrence_count": 3
        }, {
            "value": "Carrot",
            "occurrence_count": 3
        }, {
            "value": "Runner Bean",
            "occurrence_count": 3
        }, {
            "value": "Swede",
            "occurrence_count": 3
        }, {
            "value": "Turnip",
            "occurrence_count": 3
        }, {
            "value": "Parsnip",
            "occurrence_count": 3
        }, {
            "value": "Kale",
            "occurrence_count": 3
        }, {
            "value": "Spinach",
            "occurrence_count": 3
        }, {
            "value": "Artichoke",
            "occurrence_count": 3
        }, {
            "value": "Broad Bean",
            "occurrence_count": 3
        }, {
            "value": "French Bean",
            "occurrence_count": 3
        }, {
            "value": "Brocolli",
            "occurrence_count": 3
        }, {
            "value": "Cauliflower",
            "occurrence_count": 3
        }, {
            "value": "White Cabbage",
            "occurrence_count": 3
        }, {
            "value": "Red Cabbage",
            "occurrence_count": 3
        }, {
            "value": "Savoy Cabbage",
            "occurrence_count": 3
        }, {
            "value": "Corn",
            "occurrence_count": 3
        }, {
            "value": "Courgette",
            "occurrence_count": 3
        }, {
            "value": "Mange Tout",
            "occurrence_count": 3
        }, {
            "value": "Sweet Potato",
            "occurrence_count": 3
        }, {
            "value": "Pak Choi",
            "occurrence_count": 3
        }]
    }]
}
{this.createTree(data[i].nested_values, true, level)} // How to do this properly?
createTree(data, isSub, lev) {
    let level = lev || 0;
    let children = [];
    for (let i in data) {
        if (typeof(data[i].nested_values) === 'object') { // Sub array found, build structure
            children.push(
                <div class={"filter-group level-" + (level)}>
                    <div class="filter-heading">{data[i].value}</div>
                    {this.createTree(data[i].nested_values, true, level)}
                </div>
            );
        } else { // No submenu, bottom of tree
            children.push(
                <span key={i}>
                    {data[i].value}               
                </span>
            );
        }
    }
    return <div className='filter-body open'>{children}</div>;
}