diff --git a/drb-frontend/app/nodes/page.tsx b/drb-frontend/app/nodes/page.tsx index 9391b03..3478b87 100644 --- a/drb-frontend/app/nodes/page.tsx +++ b/drb-frontend/app/nodes/page.tsx @@ -19,9 +19,14 @@ export default function NodesPage() { if (!authLoading && !isAdmin && !isOperator) router.replace("/dashboard"); }, [authLoading, isAdmin, isOperator, router]); - if (authLoading || (!isAdmin && !isOperator)) return null; const [configNode, setConfigNode] = useState(null); + // Every hook must run before this guard. React tracks hooks by call order, + // so returning early on the first render and then reaching a useState on the + // next one is error #310 ("rendered more hooks than during the previous + // render") -- which crashed this whole page to a blank client-exception + // screen the moment auth resolved. + if (authLoading || (!isAdmin && !isOperator)) return null; const systemMap = Object.fromEntries(systems.map((s) => [s.system_id, s])); const pending = nodes.filter((n) => !n.configured); diff --git a/drb-frontend/app/systems/page.tsx b/drb-frontend/app/systems/page.tsx index 1d2758c..9643032 100644 --- a/drb-frontend/app/systems/page.tsx +++ b/drb-frontend/app/systems/page.tsx @@ -1188,10 +1188,15 @@ export default function SystemsPage() { if (!authLoading && !isAdmin && !isOperator) router.replace("/dashboard"); }, [authLoading, isAdmin, isOperator, router]); - if (authLoading || (!isAdmin && !isOperator)) return null; const [editing, setEditing] = useState(null); const [editIsDuplicate, setEditIsDuplicate] = useState(false); + // Every hook must run before this guard. React tracks hooks by call order, + // so returning early on the first render and then reaching a useState on the + // next one is error #310 ("rendered more hooks than during the previous + // render") -- which crashed this whole page to a blank client-exception + // screen the moment auth resolved. + if (authLoading || (!isAdmin && !isOperator)) return null; async function handleDelete(id: string) { if (!confirm("Delete this system?")) return; await c2api.deleteSystem(id);