From d4083734beafe64f59d2161046b83a785fb1794c Mon Sep 17 00:00:00 2001 From: Ally Founder Date: Tue, 11 Aug 2026 10:20:27 -0400 Subject: [PATCH] ServerDrawer: guard folder-related store lookups against undefined stores --- plugins/server-drawer/src/components/FolderItem.tsx | 7 +++++-- plugins/server-drawer/src/utils/theme.ts | 9 ++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/plugins/server-drawer/src/components/FolderItem.tsx b/plugins/server-drawer/src/components/FolderItem.tsx index 5d3eb74..9dbf634 100644 --- a/plugins/server-drawer/src/components/FolderItem.tsx +++ b/plugins/server-drawer/src/components/FolderItem.tsx @@ -30,7 +30,10 @@ function folderColor(color?: number | null): string { } function FolderBadge({ node }: { node: GuildNode }) { - const total = Flux?.useStateFromStores?.( + // Same guard as useFolderExpanded in utils/theme.ts - GuildReadStateStore is a one-shot lookup + // with no retry, and passing an undefined store into useStateFromStores throws instead of + // failing safely, which would take the whole drawer down, not just this badge. + const total = (Flux?.useStateFromStores && GuildReadStateStore) ? Flux.useStateFromStores( [GuildReadStateStore], () => { let sum = 0; @@ -40,7 +43,7 @@ function FolderBadge({ node }: { node: GuildNode }) { return sum; }, [node.children], - ) ?? 0; + ) : 0; if (total > 0) { return ( diff --git a/plugins/server-drawer/src/utils/theme.ts b/plugins/server-drawer/src/utils/theme.ts index 049dfb4..26d4606 100644 --- a/plugins/server-drawer/src/utils/theme.ts +++ b/plugins/server-drawer/src/utils/theme.ts @@ -13,7 +13,14 @@ export function useTheme() { } export function useFolderExpanded(folderId: string | number): boolean { - return Flux?.useStateFromStores?.( + // Confirmed live: an account with folders and one without exercise different code paths (this + // hook is only ever called by FolderItem, which only exists when there's a folder to render) - + // an account with no folders rendered fine while one with folders showed nothing at all. + // ExpandedGuildFolderStore is a one-shot findByStoreName at module-eval time with no retry, so + // if it hadn't registered yet, this passed [undefined] into useStateFromStores - which throws + // rather than returning safely, taking down the whole drawer render, not just this one folder. + if (!Flux?.useStateFromStores || !ExpandedGuildFolderStore) return false; + return Flux.useStateFromStores( [ExpandedGuildFolderStore], () => { const folders = ExpandedGuildFolderStore?.getExpandedFolders?.();