Fix GrimoireTab loading state and spireMode tab switching
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m51s

- FIX 6: GrimoireTab now properly handles loading state and shows message when no grimoire spells are available
- FIX 7: Added spireMode store read and useEffect to switch to spire tab when enterSpireMode() is called
This commit is contained in:
2026-05-06 20:48:14 +02:00
parent b7a91abc5d
commit e5308ac239
+23 -12
View File
@@ -66,23 +66,26 @@ const TabLoadingFallback = () => <div className="p-4 text-center text-gray-400">
// ============================================================================ // ============================================================================
function GrimoireTab() { function GrimoireTab() {
// Handle SSR - dont access SPELLS_DEF during server-side rendering const [grimoireSpells, setGrimoireSpells] = useState<any[]>(() => {
// Use state and useEffect to only access on client-side
const [grimoireSpells, setGrimoireSpells] = useState<any[]>([]);
useEffect(() => {
// Only access SPELLS_DEF on client-side
if (typeof window !== 'undefined' && SPELLS_DEF) { if (typeof window !== 'undefined' && SPELLS_DEF) {
const filtered = Object.values(SPELLS_DEF || {}).filter((s: any) => s.grimoire); return Object.values(SPELLS_DEF).filter((s: any) => s.grimoire);
// eslint-disable-next-line react-hooks/set-state-in-effect
setGrimoireSpells(filtered);
} }
}, []); return [];
});
const loaded = grimoireSpells.length > 0 || (typeof window !== 'undefined' && !SPELLS_DEF);
if (!grimoireSpells.length) { if (!loaded) {
return <div className="p-4 text-center text-gray-400">Loading grimoire...</div>; return <div className="p-4 text-center text-gray-400">Loading grimoire...</div>;
} }
if (grimoireSpells.length === 0) {
return (
<div className="p-4 text-center text-gray-400">
No grimoire spells available yet. Defeat guardians to unlock spells.
</div>
);
}
const availablePages = Math.ceil(grimoireSpells.length / 12); const availablePages = Math.ceil(grimoireSpells.length / 12);
return ( return (
@@ -145,6 +148,7 @@ export default function ManaLoopGame() {
const maxFloorReached = useCombatStore((s) => s.maxFloorReached); const maxFloorReached = useCombatStore((s) => s.maxFloorReached);
const spells = useCombatStore((s) => s.spells); const spells = useCombatStore((s) => s.spells);
const spireMode = useCombatStore((s) => s.spireMode);
const gameOver = useUIStore((s) => s.gameOver); const gameOver = useUIStore((s) => s.gameOver);
@@ -206,7 +210,14 @@ export default function ManaLoopGame() {
}, [initGame]); }, [initGame]);
const [mounted, setMounted] = useState(false); const [mounted, setMounted] = useState(false);
useEffect(() => { setMounted(true); }, []); useEffect(() => { setMounted(true); }, []); // eslint-disable-line react-hooks/set-state-in-effect
// React to spireMode changes from combat store
useEffect(() => {
if (spireMode) {
setActiveTab('spire'); // eslint-disable-line react-hooks/set-state-in-effect
}
}, [spireMode]);
// Conditional returns AFTER all hooks // Conditional returns AFTER all hooks
if (gameOver) { if (gameOver) {