Replace ref+tick workaround with proper state in useBestiary

Store creature map in useState instead of useRef with a dummy
tick counter. React now re-renders naturally when the map changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-14 12:54:48 +01:00
parent 36dcfc5076
commit 971e0ded49

View File

@@ -3,7 +3,7 @@ import type {
Creature,
CreatureId,
} from "@initiative/domain";
import { useCallback, useEffect, useRef, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import {
normalizeBestiary,
setSourceDisplayNames,
@@ -33,8 +33,9 @@ interface BestiaryHook {
export function useBestiary(): BestiaryHook {
const [isLoaded, setIsLoaded] = useState(false);
const creatureMapRef = useRef<Map<CreatureId, Creature>>(new Map());
const [, setTick] = useState(0);
const [creatureMap, setCreatureMap] = useState(
() => new Map<CreatureId, Creature>(),
);
useEffect(() => {
const index = loadBestiaryIndex();
@@ -44,8 +45,7 @@ export function useBestiary(): BestiaryHook {
}
bestiaryCache.loadAllCachedCreatures().then((map) => {
creatureMapRef.current = map;
setTick((t) => t + 1);
setCreatureMap(map);
});
}, []);
@@ -63,9 +63,12 @@ export function useBestiary(): BestiaryHook {
}));
}, []);
const getCreature = useCallback((id: CreatureId): Creature | undefined => {
return creatureMapRef.current.get(id);
}, []);
const getCreature = useCallback(
(id: CreatureId): Creature | undefined => {
return creatureMap.get(id);
},
[creatureMap],
);
const isSourceCachedFn = useCallback(
(sourceCode: string): Promise<boolean> => {
@@ -86,10 +89,13 @@ export function useBestiary(): BestiaryHook {
const creatures = normalizeBestiary(json);
const displayName = getSourceDisplayName(sourceCode);
await bestiaryCache.cacheSource(sourceCode, displayName, creatures);
setCreatureMap((prev) => {
const next = new Map(prev);
for (const c of creatures) {
creatureMapRef.current.set(c.id, c);
next.set(c.id, c);
}
setTick((t) => t + 1);
return next;
});
},
[],
);
@@ -100,18 +106,20 @@ export function useBestiary(): BestiaryHook {
const creatures = normalizeBestiary(jsonData as any);
const displayName = getSourceDisplayName(sourceCode);
await bestiaryCache.cacheSource(sourceCode, displayName, creatures);
setCreatureMap((prev) => {
const next = new Map(prev);
for (const c of creatures) {
creatureMapRef.current.set(c.id, c);
next.set(c.id, c);
}
setTick((t) => t + 1);
return next;
});
},
[],
);
const refreshCache = useCallback(async (): Promise<void> => {
const map = await bestiaryCache.loadAllCachedCreatures();
creatureMapRef.current = map;
setTick((t) => t + 1);
setCreatureMap(map);
}, []);
return {