繁体   English   中英

需要帮助在 React 中使用给定的 json 结构创建文件夹树组件

[英]Need help creating a folder tree component in React with the given json structure

我正在尝试构建一个文件夹树组件,最初该组件只会呈现第一层的项目名称(item1、item2、item3),然后当单击特定项目时,它会显示下一层列出的所有内容对于该项目(即单击item1将显示item1.1item1.2,单击item1.1将显示item1.1.1 )。 这应该在一个循环中完成,直到它到达只有属性(attr1、attr2、attr3)的最后一层。

注意:出于演示目的,我已经简化了项目名称,但实际上它们并不遵循特定的模式/命名系统。

import React, {useState, useEffect} from 'react';


const Testing = () => {
    const [expand, setExpand] = useState(false);
    
    const data = {
        "item1": {
            "item1.1": {
                "item1.1.1": {
                    "item1.1.1.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": []
                    }
                }
            },
            "item1.2": {
                "item1.2.1": {
                    "item1.2.1.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": []
                    }
                }
            }
        },
        "item2": {
            "item2.1": {
                "item2.1.1": {
                    "item2.1.1.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": []
                    }
                },
                "item2.1.2": {
                    "item2.1.2.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": []
                    },
                    "item2.1.2.2": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": []
                    }
                }
            }
        },
        "item3": {
            "item3.1": {
                "item3.1.1": {
                    "item3.1.1.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": []
                    }
                },
                "item3.1.2": {
                    "attr1": [],
                    "attr2": "",
                    "attr3": []
                }
            }
        }

    }

    function parse(data) {
        if (typeof data === 'object') {
            return (
                <li>
                    <ul>
                        {Object.entries(data).map(([key, value]) => (
                            <>
                                <li>
                                    {key}: {typeof value === 'string' ? value : ''}
                                </li>
                                {parse(value)}
                            </>
                        ))}
                    </ul>
                </li>
            );
        }
        if (typeof data === 'object') return (<li>{data}</li>);
        return null;
    }
    
    return (
        <div>
            <div className="App">
                {Object.entries(data).map(([key, value]) => {
                    return (
                        <ul>
                            <span onClick={() => setExpand(!expand)}>{key}</span>
                            <br />
                            <div style={{ display: expand ? "block" : "none", paddingLeft: 15 }}>
                                {parse(value)}
                            </div>
                        </ul>
                    );
                })}
            </div>
        </div>
    )
}

export default Testing;

这是我现在用上面的代码得到的输出图片: current output ; 它在列表中显示 item1、item2、item3; 但是当我点击它们中的任何一个时,它只会呈现其他所有内容,我正在尝试找到一种方法,使其行为类似于文件目录树,如下面的演示所示: https ://codesandbox.io/s /文件夹结构-t6oj4

问题在于,在演示中,他们使用了一个递归组件,该组件具有自己的expand状态,并通过钩子进行管理。 因此,每个Folder都将具有其范围内的expand变量的不同值。

另一方面,您的Testing组件管理单个expand状态,并且整个渲染为每个“文件夹”使用该状态,这就是为什么当您单击文件夹时它会切换整个组件的状态,您应该做的是重构您的组件,以便它还在每个文件夹中管理自己的状态,就像在演示中一样:

import React, { useState } from "react";

function Folder ({ name, file }) {
  const [expand, setExpand] = useState(false);
  if (typeof file !== "object") return <span>{file}</span>;
  return (
    <div>
      <span onClick={() => setExpand(!expand)}>{name}</span>
      <br/>
      <div style={{ display: expand ? "block" : "none", paddingLeft: 15 }} >
        {
          Object.entries(file).map(([key, value]) => (
            <Folder key={key} name={key} file={value} />
          ))
        }
      </div>
    </div>
  );
}

然后在你的组件中调用它:

import React from 'react';


const Testing = () => {
    const data = {
        "item1": {
            "item1.1": {
                "item1.1.1": {
                    "item1.1.1.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": []
                    }
                }
            },
            "item1.2": {
                "item1.2.1": {
                    "item1.2.1.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": []
                    }
                }
            }
        },
        "item2": {
            "item2.1": {
                "item2.1.1": {
                    "item2.1.1.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": []
                    }
                },
                "item2.1.2": {
                    "item2.1.2.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": []
                    },
                    "item2.1.2.2": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": []
                    }
                }
            }
        },
        "item3": {
            "item3.1": {
                "item3.1.1": {
                    "item3.1.1.1": {
                        "attr1": [],
                        "attr2": "",
                        "attr3": []
                    }
                },
                "item3.1.2": {
                    "attr1": [],
                    "attr2": "",
                    "attr3": []
                }
            }
        }

    }
    
    return (
        <div>
            <div className="App">
                <Folder name="/root" file={data} />
            </div>
        </div>
    )
}

编辑:重构代码,以便只有选定的文件夹在单击时展开

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM