Fix hooks order in Table (run replay-step hooks before the loading guard).

This commit is contained in:
Greyson Parrelli
2026-07-23 08:22:00 -04:00
parent 996bb861a9
commit 169b21d6a8
+16 -15
View File
@@ -14,22 +14,12 @@ import { EventLog, battleLogLines } from './EventLog'
export function Table({ session, onLeave }: { session: Session; onLeave: () => void }) {
const { view, error, connected, send } = useGame(session)
if (!view) {
return (
<div className="centered muted">
{connected ? 'Loading game…' : 'Connecting…'}
</div>
)
}
const you = view.players[view.youSeat]
const opponents = view.players.filter((p) => p.seat !== view.youSeat)
// Battle replay step lives here (not inside BattlePhase) so the event log,
// a sibling, can render the battle narration up to the same step. Deriving
// the effective step from the current battle round resets it to 0 whenever a
// new battle arrives, without a separate effect.
const battleRound = view.battle?.round ?? -1
// new battle arrives, without a separate effect. These hooks must run on
// every render (before any early return) to satisfy the rules of hooks.
const battleRound = view?.battle?.round ?? -1
const [stepState, setStepState] = useState<{ round: number; step: number }>({
round: -1,
step: 0,
@@ -44,12 +34,23 @@ export function Table({ session, onLeave }: { session: Session; onLeave: () => v
const battleLines = useMemo(
() =>
view.phase === 'battle' && view.battle?.events
view?.phase === 'battle' && view.battle?.events
? battleLogLines(view.battle.events, step)
: undefined,
[view.phase, view.battle, step],
[view, step],
)
if (!view) {
return (
<div className="centered muted">
{connected ? 'Loading game…' : 'Connecting…'}
</div>
)
}
const you = view.players[view.youSeat]
const opponents = view.players.filter((p) => p.seat !== view.youSeat)
return (
<div className="table">
<header className="topbar">