fix: React error #310 — useMemo after early return in detail panel

Move threadChain useMemo before the `if (!entry) return null` early
return to keep hook call order stable between renders. When entry was
null, the hook was skipped, causing "Rendered more hooks than during
the previous render" crash on subsequent renders with entry set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-12 00:23:15 +02:00
parent 0cc14a96e9
commit d8a10fadc0
@@ -177,26 +177,16 @@ export function RegistryEntryDetail({
setTimeout(() => setCopiedPath(null), 2000);
}, []);
if (!entry) return null;
const dir = DIRECTION_CONFIG[entry.direction] ?? DIRECTION_CONFIG.intrat;
const DirIcon = dir.icon;
const status = STATUS_CONFIG[entry.status] ?? STATUS_CONFIG.deschis;
const overdueDays =
entry.status === "deschis" ? getOverdueDays(entry.deadline) : null;
const isOverdue = overdueDays !== null && overdueDays > 0;
const threadParent = entry.threadParentId
? allEntries.find((e) => e.id === entry.threadParentId)
: null;
const threadChildren = allEntries.filter(
(e) => e.threadParentId === entry.id,
);
// Build full chain for mini flow diagram
// Build full chain for mini flow diagram (must be before early return to keep hook order stable)
const threadChain = useMemo(() => {
if (!threadParent && threadChildren.length === 0) return [];
if (!entry) return [];
const threadParentEntry = entry.threadParentId
? allEntries.find((e) => e.id === entry.threadParentId)
: null;
const threadChildEntries = allEntries.filter(
(e) => e.threadParentId === entry.id,
);
if (!threadParentEntry && threadChildEntries.length === 0) return [];
const byId = new Map(allEntries.map((e) => [e.id, e]));
// Walk up to root
let root = entry;
@@ -222,7 +212,24 @@ export function RegistryEntryDetail({
}
chain.sort((a, b) => a.date.localeCompare(b.date));
return chain;
}, [entry, threadParent, threadChildren, allEntries]);
}, [entry, allEntries]);
if (!entry) return null;
const dir = DIRECTION_CONFIG[entry.direction] ?? DIRECTION_CONFIG.intrat;
const DirIcon = dir.icon;
const status = STATUS_CONFIG[entry.status] ?? STATUS_CONFIG.deschis;
const overdueDays =
entry.status === "deschis" ? getOverdueDays(entry.deadline) : null;
const isOverdue = overdueDays !== null && overdueDays > 0;
const threadParent = entry.threadParentId
? allEntries.find((e) => e.id === entry.threadParentId)
: null;
const threadChildren = allEntries.filter(
(e) => e.threadParentId === entry.id,
);
return (
<Sheet open={open} onOpenChange={onOpenChange}>