fix(Snackbar): apply hidden state when animation reports finished:false under Fabric#5022
Open
momomuchu wants to merge 1 commit into
Open
fix(Snackbar): apply hidden state when animation reports finished:false under Fabric#5022momomuchu wants to merge 1 commit into
momomuchu wants to merge 1 commit into
Conversation
…d:false under Fabric — callstack#4951 Under the New Architecture (Fabric), `Animated.timing` can fire its `start` callback with `{ finished: false }` even when the hide animation completes naturally (no interruption). The previous code guarded `setHidden(true)` behind `if (finished)`, so the Snackbar stayed mounted forever on Fabric after `visible` became false. The fix removes the guard and calls `setHidden(true)` unconditionally in the animation callback, mirroring the show-path fix from PR callstack#4447 which addressed the same class of Fabric noise for `handleOnVisible`. The sole trade-off is a mid-hide interrupt: if `visible` flips back to `true` while the hide animation is running, `setHidden(true)` fires, but the subsequent render immediately calls `setHidden(false)` via `handleOnVisible`, causing at most a one-frame visual snap — strictly better than a permanently stuck Snackbar that no state change can clear. Adds a regression test that mocks `Animated.timing` to deliver `{ finished: false }` and asserts the component unmounts cleanly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes a New Architecture (Fabric) Snackbar hide/unmount regression where the hide animation callback may report { finished: false }, preventing hidden from being set and leaving the component mounted after visible={false}.
Changes:
- Updates the hide animation completion handling in
Snackbarto ensure the hidden/unmount state is applied even when Fabric reportsfinished:false. - Adds a regression test that mocks
Animated.timingto invoke its callback with{ finished: false }and asserts the Snackbar unmounts.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/components/Snackbar.tsx | Adjusts hide-animation completion behavior to prevent stuck-mounted Snackbar under Fabric. |
| src/components/tests/Snackbar.test.tsx | Adds regression coverage for Fabric’s finished:false animation callback noise on the hide path. |
Comment on lines
207
to
213
| Animated.timing(opacity, { | ||
| toValue: 0, | ||
| duration: 100 * scale, | ||
| useNativeDriver: true, | ||
| }).start(({ finished }) => { | ||
| if (finished) { | ||
| setHidden(true); | ||
| } | ||
| }).start(() => { | ||
| setHidden(true); | ||
| }); |
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.
Summary
Fixes #4951 — the
Snackbarstays mounted aftervisiblebecomesfalseunder the New Architecture (Fabric), on iOS and Android.Root cause
The hide animation gated the hidden state behind
finished:Under Fabric,
Animated.timingcan fire itsstartcallback with{ finished: false }even when the hide animation completes naturally (no interruption). The guard then skipssetHidden(true), so the Snackbar never unmounts. This is the same class of Fabric callback noise that PR #4447 addressed for the show path (handleOnVisible); the hide path was missed.Fix
Call
setHidden(true)unconditionally in the hide animation callback, mirroring #4447.Trade-off (documented in the commit): if
visibleflips back totruemid-hide,setHidden(true)fires but the next render immediately callssetHidden(false)viahandleOnVisible— at most a one-frame snap, strictly better than a permanently stuck Snackbar that no state change can clear.Test
Adds a regression test that mocks
Animated.timingto invoke its callback with{ finished: false }and asserts the Snackbar unmounts aftervisiblebecomesfalse. FullSnackbar.test.tsxsuite: 7 passed.Closes #4951