UI: Improve Tree context performance

This commit is contained in:
Fuma Nama
2025-03-30 17:26:58 +08:00
parent c3c8918d54
commit 22aeafb308
4 changed files with 16 additions and 9 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-ui': patch
---
Improve Tree context performance
@@ -284,6 +284,7 @@ function build(ctx: PageTreeBuilderContext): PageTree.Root {
const folder = buildFolderNode(root, true, ctx);
return {
$id: 'root',
name: folder.name,
children: folder.children,
};
@@ -466,8 +466,7 @@ export function SidebarPageTree(props: {
return (
<Fragment key={root.$id}>{renderSidebarList(root.children, 1)}</Fragment>
);
// eslint-disable-next-line react-hooks/exhaustive-deps -- root.id is enough
}, [props.components, root.$id]);
}, [props.components, root]);
}
function PageTreeFolder({
+9 -7
View File
@@ -13,18 +13,20 @@ interface TreeContextType {
const TreeContext = createContext<TreeContextType>('TreeContext');
const PathContext = createContext<PageTree.Node[]>('PathContext', []);
export function TreeContextProvider({
children,
tree,
}: {
export function TreeContextProvider(props: {
tree: PageTree.Root;
children: ReactNode;
}) {
const nextIdRef = useRef(0);
const pathname = usePathname();
// I found that object-typed props passed from a RSC will be re-constructed, hence breaking all hooks' dependencies
// using the id here to make sure this never happens
// eslint-disable-next-line react-hooks/exhaustive-deps
const tree = useMemo(() => props.tree, [props.tree.$id ?? props.tree]);
const path = useMemo(
() => searchPath(tree.children, pathname) ?? [],
[pathname, tree],
[tree, pathname],
);
const root =
@@ -33,9 +35,9 @@ export function TreeContextProvider({
return (
<TreeContext.Provider
value={useMemo(() => ({ root: root as TreeContextType['root'] }), [root])}
value={useMemo(() => ({ root }) as TreeContextType, [root])}
>
<PathContext.Provider value={path}>{children}</PathContext.Provider>
<PathContext.Provider value={path}>{props.children}</PathContext.Provider>
</TreeContext.Provider>
);
}