Skip to Content

useTreeView

useTreeView takes the flat array of entities a listing page already has and builds the client-side tree that Tree View renders. It links nodes through their parent relation, sorts siblings, and owns the expand/collapse state.


Import

import { useTreeView } from "@phpcreation/frontend-crud-react-nextjs-bundle/utils/hooks";

Signature

const { treeData, // TreeItem[] root nodes, children nested itemsMap, // Map<number, TreeItem> every node by id visibleItems, // TreeItem[] flattened rows to render, respecting expansion expandedRows, // Set<number> ids of expanded nodes toggleTreeRow, // (id: number) => void expandAll, // () => void collapseAll, // () => void expandNodeAndParents, // (id: number) => void expand a node and all its ancestors findNode, // (id | predicate) => TreeItem | null isTreeEmpty, // boolean } = useTreeView(data, options);
interface TreeViewOptions { idField?: string; // default "id" parentField?: string; // default "parent" levelField?: string; // default "lvl" sortField?: string; // default "ref" defaultExpandLevel?: number; // default 1, levels expanded on load }

Each TreeItem wraps the original entity:

interface TreeItem<T> { id: number; item: T; // the raw entity level: number; // from levelField children: TreeItem<T>[]; parentId: number | null; }

Behavior

  • Parenting. Nodes attach to their parent through parentField. A node whose parent is not in the current page of data becomes a root, so a filtered subtree still renders.
  • Sibling order. Siblings sort by lft ascending. Nodes without a usable lft fall back to sortField, then id. This keeps the display order equal to the stored tree order.
  • Expansion survives refetches. When data changes (a move, an inline edit, a filter), previously expanded ids that still exist stay expanded. defaultExpandLevel only adds to that set.
  • visibleItems is what the table maps over: a depth-first flattening of treeData that skips children of collapsed nodes.

Usage

How ListingTable uses it:

const { visibleItems, toggleTreeRow, expandAll, collapseAll, expandedRows, expandNodeAndParents, } = useTreeView(data, { parentField: "parent", levelField: "lvl", defaultExpandLevel: 0, }); // ?anchor=<id> deep link: open the path to the node useEffect(() => { if (anchoredId) expandNodeAndParents(Number(anchoredId)); }, [anchoredId, data]);

Last updated on