fix(react-chess-game): board stuck on old position after puzzle change mid-animation#86
Merged
Merged
Conversation
…on loads Solving a puzzle with a promotion move starts a 300ms animation inside react-chessboard whose timer is never cleared on position change; when onSolve immediately swapped the puzzle, the stale timer reapplied the previous puzzle's position over the new one, leaving the board stuck on the old state (#83). useChessGame now exposes a positionId that increments whenever a new position is loaded (fen prop change or setPosition) but not on moves, and Board keys the Chessboard on it so a freshly loaded position always mounts a clean board. Verified in a real browser via Storybook that the flicker is gone and regular move animations still play. Closes #83 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 2762a13 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Issue #83 reports that
onSolvefires before the promotion animation finishes: if the consumer swaps the puzzle inonSolve, the board flickers back to the old state.Diagnosis (verified in a real browser via Storybook + Playwright)
Reproduced on main, and it's worse than a flicker: sampling the DOM after the solving promotion move, the board shows the new puzzle at t≈40ms but at t≈330ms it goes back to the old puzzle (queen on d8) and stays there.
The root cause is in react-chessboard v5: the branch that animates promotions registers a
setTimeout(300ms)that reapplies the destination position, and never clears it when the position changes again (it doesreturnwithout a cleanup). Our puzzle switch arrives withanimationDurationInMs: 0, so its timer fires immediately and the stale promotion timer then overwrites everything.Fix
As suggested in the issue ("if the board has changed then the animation shouldn't take place"):
useChessGameexposes apositionId, incremented only when a new position is loaded (fenprop change orsetPosition), never on movesBoarduseskey={positionId}on the<Chessboard>: on position change the board remounts cleanly and stale timers die with the unmounted instanceThis also covers resetting the same puzzle mid-animation, not just puzzle changes.
Verification
transition: transform 300mspresent on e2-e4)promotionAnimationFlicker.test.tsx): fails without the fix, passes with itpositionIdcontractThe upstream react-chessboard bug (uncleared timeout in the promotion branch) deserves a separate report.
Closes #83
🤖 Generated with Claude Code