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 }) { export function Table({ session, onLeave }: { session: Session; onLeave: () => void }) {
const { view, error, connected, send } = useGame(session) 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, // 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 // 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 // the effective step from the current battle round resets it to 0 whenever a
// new battle arrives, without a separate effect. // new battle arrives, without a separate effect. These hooks must run on
const battleRound = view.battle?.round ?? -1 // 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 }>({ const [stepState, setStepState] = useState<{ round: number; step: number }>({
round: -1, round: -1,
step: 0, step: 0,
@@ -44,12 +34,23 @@ export function Table({ session, onLeave }: { session: Session; onLeave: () => v
const battleLines = useMemo( const battleLines = useMemo(
() => () =>
view.phase === 'battle' && view.battle?.events view?.phase === 'battle' && view.battle?.events
? battleLogLines(view.battle.events, step) ? battleLogLines(view.battle.events, step)
: undefined, : 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 ( return (
<div className="table"> <div className="table">
<header className="topbar"> <header className="topbar">