/*
实现一个循环引用树形组件
要求:
1. 要考虑数据循环引用问题。
2. 除了 React,Antd 外,不能使用任何第三方库,只能使用浏览器原生 API
如:存在三条数据 A、B、C:
- A 的子元素为 B、C
- B 的子元素为 C、A
- C 的子元素为 A、B
则构成 A -> B -> C -> A 的循环引用。
渲染结果如下图所示,其中每个节点都可以展开,且可以无限递归展开。
https://s3plus.meituan.net/v1/mss_bf7e9f1c1cc54cfb819fc8ffcf965b40/static/WX20201209-113933%402x.png
*/
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import { Tree } from "antd";
const a = { id: 1, title: "A" };
const b = { id: 2, title: "B" };
const c = { id: 3, title: "C" };
const d = { id: 4, title: "D" };
const e = { id: 5, title: "E" };
const f = { id: 6, title: "F" };
const g = { id: 7, title: "G" };
a.children = [b, d, e];
b.children = [c, e, f];
c.children = [e, g, a];
d.children = [e, f, g];
e.children = [a, b, c];
f.children = [c, d, e];
g.children = [b, e, f];
const data = [a, b, c, d, e, f, g];
const ROOT = 0;
const Demo = () => {
const [entities] = useState(() => {
return [a, b, c, d, e, f, g].reduce((r, d) => {
r[d.id] = d;
return r;
}, {});
});
const [childrenMap, setChildrenMap] = useState(() => {
return {
[ROOT]: data.map((d) => ({
id: d.id,
title: d.title,
key: Math.random()
}))
};
});
const onLoadData = React.useCallback((parent) => {
return new Promise((resolve) => {
if (parent.children) return resolve();
setTimeout(() => {
});
});
}, []);
const treeData = React.useMemo(() => {
const iter = (children) => {
if (!children) return;
return children.map(({ key, id }) => {
const item = entities[id];
if (!item) return null;
return null;
});
};
return iter(childrenMap[ROOT]);
}, [entities, childrenMap]);
return <Tree loadData={onLoadData} treeData={treeData} />;
};
export default Demo;