#reactjs #material-ui #treeview
Вопрос:
поэтому я пытаюсь создать дерево, используя представление дерева в пользовательском интерфейсе Material ( https://material-ui.com/components/tree-view/). Мы можем взять пример с их страницы:
const data = {
id: 'root',
name: 'Parent',
children: [
{
id: '1',
name: 'Child - 1',
},
{
id: '3',
name: 'Child - 3',
children: [
{
id: '4',
name: 'Child - 4',
},
],
},
],
};
const useStyles = makeStyles({
root: {
height: 110,
flexGrow: 1,
maxWidth: 400,
},
});
export default function RecursiveTreeView() {
const classes = useStyles();
const renderTree = (nodes) => (
<TreeItem key={nodes.id} nodeId={nodes.id} label={nodes.name}>
{Array.isArray(nodes.children) ? nodes.children.map((node) => renderTree(node)) : null}
</TreeItem>
);
return (
<TreeView
className={classes.root}
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpanded={['root']}
defaultExpandIcon={<ChevronRightIcon />}
>
{renderTree(data)}
</TreeView>
);
}
Что я хочу сделать, так это всякий раз, когда я нажимаю на узел, запускать какую-либо функцию, только если это конечный узел. Реквизит «onNodeSelect», который есть в treeview, дает мне только идентификатор узла, но не любую другую информацию об узле. Я знаю, что один из способов состоит в том, чтобы найти исходный json для этого идентификатора и найти узел, а затем проверить, есть ли у него дети, но мой json довольно большой, и я бы не хотел этого делать. Как-нибудь по-другому?
Ответ №1:
Потенциально вы можете использовать щелчок по ярлыку компонента TreeItem и отключить часть «выбор» в представлении дерева (например, использовать отключение выбора в представлении дерева).
Тогда ваш код может стать
const handleTreeItemClick = (node) => {
if( node.children amp;amp; node.children.length ) {
// do some stuff
} else {
// do something else
}
}
const renderTree = (nodes) => (
<TreeItem
key={nodes.id}
nodeId={nodes.id}
label={nodes.name}
onLabelClick={() => handleTreeItemClick(nodes)}
>
{Array.isArray(nodes.children) ? nodes.children.map((node) => renderTree(node)) : null}
</TreeItem>
);
В противном случае вы могли бы создать хэш данных с идентификаторами, указывающими на узел данных (не уверены в производительности хэширования большого объекта json?), а затем просто искать значение из хэша, а не искать каждый раз. Раздражает, я знаю, например.
// do this outside of the render, perhaps in a redux selector or reducer
const hashMethod = (nodes, hash = {}) => {
return nodes.reduce((h, node) => {
h[node.id] = node;
if( node.children) {
h = hashMethod(node.children, h);
}
return h;
}, hash);
}
// sorry turned it into an array first so I can use reduce easier
const hashedData = hashMethod([data]);
Затем в обработчике onNodeSelect внутри компонента (для одного выбора)
const handleNodeSelect = (nodeId) => {
const node = hashedData(nodeId);
// do what you need with the data
}