From 32fbb039cad2f83d0d8159273e231e9db38492fd Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Jul 2026 09:59:22 +0000 Subject: [PATCH] fix: adjust promotion-rank state during render instead of in an effect Replaces the prevRankRef + useEffect promotion detector with the render-phase state-adjustment pattern recommended by the React docs, resolving the react-hooks/set-state-in-effect lint error. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Dsq9LChvMw1JVyhQj9roav --- src/components/GameProvider.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/GameProvider.tsx b/src/components/GameProvider.tsx index 53c3b79..964c761 100644 --- a/src/components/GameProvider.tsx +++ b/src/components/GameProvider.tsx @@ -30,7 +30,7 @@ export default function GameProvider() { const [showLevelNavigator, setShowLevelNavigator] = useState(false); const [isPanelCollapsed, setIsPanelCollapsed] = useState(false); const [promotionRank, setPromotionRank] = useState(null); - const prevRankRef = useRef(null); + const [prevRank, setPrevRank] = useState(null); const rightPanelRef = useRef(null); const { currentLevel, totalXp, currentStreak, rehydrateFleet } = useGameStore(); @@ -38,13 +38,14 @@ export default function GameProvider() { // so every rank up to Managing Director is actually reachable. const rank = rankInfo(totalXp); - // Detect rank promotions and surface the banner. - useEffect(() => { - if (prevRankRef.current !== null && prevRankRef.current !== rank.name) { + // Detect rank promotions and surface the banner. State is adjusted during + // render (not in an effect) per https://react.dev/learn/you-might-not-need-an-effect + if (prevRank !== rank.name) { + if (prevRank !== null) { setPromotionRank(rank.name); } - prevRankRef.current = rank.name; - }, [rank.name]); + setPrevRank(rank.name); + } useEffect(() => { initDatabase()