mui-nav-menu
Version:
Navigation menu component based on material ui
55 lines (54 loc) • 1.96 kB
JavaScript
import React, { useCallback, useRef } from "react";
import MenuItemGroup from "../MenuItemGroup";
export const useMenuNodes = () => {
const nodeMapRef = useRef({});
const clearNodes = useCallback(() => {
nodeMapRef.current = {};
}, []);
const registerNode = useCallback((nodeData) => {
nodeMapRef.current[nodeData.id] = nodeData;
}, []);
const getNode = useCallback((menuId) => {
return nodeMapRef.current[menuId];
}, []);
const getChildrenIds = useCallback((parentId, excludeDisabled) => {
return Object.values(nodeMapRef.current)
.filter((node) => node.parentId === parentId)
.filter((node) => (excludeDisabled ? !node.disabled : true))
.sort((a, b) => a.index - b.index)
.map((child) => child.id);
}, []);
const getDescendantIds = useCallback((parentId) => {
return getChildrenIds(parentId).reduce((acc, id) => {
return [...acc, id, getDescendantIds(id)].flat();
}, []);
}, []);
const processItem = useCallback((item, parentId, index) => {
const { id, label, disabled, children, link, type } = item.props;
const isGroup = item.type == MenuItemGroup;
const childrens = React.Children.toArray(children);
if (!isGroup && id && label) {
//exclude group node
registerNode({
id,
parentId,
label: label,
disabled: disabled,
link,
hasChildren: !!(childrens && childrens.length),
});
}
if (childrens && childrens.length) {
React.Children.forEach(childrens, (child, index) => {
processItem(child, isGroup ? parentId : id, index);
});
}
}, []);
return {
processItem,
getChildrenIds,
getNode,
clearNodes,
getDescendantIds,
};
};