Fix rules-of-hooks crash on CompanySkills when company context resolves

The folder-rail scoped-counts useMemo (railSkillFolderResult) sat below the
"if (!selectedCompanyId)" early return, so the page threw "Rendered more
hooks than during the previous render" the moment the companies query
resolved after a fresh load. Hoist it (with its input consts) above the
early return.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-07-15 17:13:24 +00:00
1 parent 8fad2a654c
commit be8bbf40b9
1 file changed
+27 -27
+27 -27
View File
@@ -4538,6 +4538,33 @@ export function CompanySkills() {
},
});
const skillFolderResult = skillFoldersQuery.data ?? null;
const showInstalledFolders = isDiscovery && discoveryTab === "installed";
// Rail counts reflect the current category/search scope, never the folder
// filter itself (ux-spec §5.3).
const railSkillFolderResult = useMemo(() => {
if (!skillFolderResult || discoveryTab !== "installed") return skillFolderResult;
const scoped = discoveryTabCards.filter((card) => {
if (discoveryCategory && !card.categories.includes(discoveryCategory)) return false;
return discoveryMatchesSearch(card, discoverySearch.trim());
});
const counts = new Map<string, number>();
let unfiled = 0;
for (const card of scoped) {
if (card.folderId) counts.set(card.folderId, (counts.get(card.folderId) ?? 0) + 1);
else unfiled += 1;
}
return {
...skillFolderResult,
allCount: scoped.length,
unfiledCount: unfiled,
folders: skillFolderResult.folders.map((folder) => ({
...folder,
itemCount: counts.get(folder.id) ?? 0,
})),
};
}, [skillFolderResult, discoveryTab, discoveryTabCards, discoveryCategory, discoverySearch]);
if (!selectedCompanyId) {
return <EmptyState icon={Boxes} message="Select a company to manage skills." />;
}
@@ -4581,33 +4608,6 @@ export function CompanySkills() {
const studioDescription = studioForkFromId
? "Review the fork metadata and create an editable company copy."
: "Create an editable company skill in the Paperclip workspace.";
const skillFolderResult = skillFoldersQuery.data ?? null;
const showInstalledFolders = isDiscovery && discoveryTab === "installed";
// Rail counts reflect the current category/search scope, never the folder
// filter itself (ux-spec §5.3).
const railSkillFolderResult = useMemo(() => {
if (!skillFolderResult || discoveryTab !== "installed") return skillFolderResult;
const scoped = discoveryTabCards.filter((card) => {
if (discoveryCategory && !card.categories.includes(discoveryCategory)) return false;
return discoveryMatchesSearch(card, discoverySearch.trim());
});
const counts = new Map<string, number>();
let unfiled = 0;
for (const card of scoped) {
if (card.folderId) counts.set(card.folderId, (counts.get(card.folderId) ?? 0) + 1);
else unfiled += 1;
}
return {
...skillFolderResult,
allCount: scoped.length,
unfiledCount: unfiled,
folders: skillFolderResult.folders.map((folder) => ({
...folder,
itemCount: counts.get(folder.id) ?? 0,
})),
};
}, [skillFolderResult, discoveryTab, discoveryTabCards, discoveryCategory, discoverySearch]);
return (
<>
{policyDenial.denial ? (