Snackbar stays mounted after `visible=false` under new architecture (iOS + Android)
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 78/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- react-native, typescript
- Domain
- mobile
Research direction
Read src/components/Snackbar.tsx, focusing on handleOnHidden and the hide animation callback; compare its behavior with the show-path workaround in #4447. Reproduce with Fabric enabled by toggling visible from true to false on iOS or Android. Done means the hide animation leaves the Snackbar unmounted and hidden even when the callback reports finished: false.
Written by the indexing model from the issue text.
Description
Summary
Under React Native's new architecture (Fabric), paper's <Snackbar> can get stuck mounted at non-zero opacity after visible is set to false. The hide animation runs visually, but the component never unmounts and stays visible on screen until something else forces a remount.
Sister bug to #3775 / #4445 (which were Android-only show path, fixed by #4447). This is the hide path, and reproduces on both iOS and Android with the new arch enabled.
Root cause
src/components/Snackbar.tsx, handleOnHidden:
Animated.timing(opacity, {
toValue: 0,
duration: 100 * scale,
useNativeDriver: true,
}).start(({ finished }) => {
if (finished) { // ← this guard is the problem under Fabric
setHidden(true);
}
});
Under Fabric, this start({finished}) callback fires with finished: false even when nothing has interrupted the animation. setHidden(true) is the only thing that makes the component return null and actually unmount, so the snackbar stays rendered at whatever opacity the (visually-running) animation reached.
The parallel show-path fix #4447 split handleOnVisible from animateShow to work around the same Fabric noise. The hide path was not touched and still carries the guard.
Expected behaviour
After visible={false}, the Snackbar component unmounts cleanly (hidden flips to true) once the hide animation completes, regardless of the finished flag.
Current behaviour
After visible={false}:
- The hide animation fires (opacity 1 → 0).
- The
startcallback fires withfinished: false. setHidden(true)is skipped.- The component stays mounted; nothing in the React state can clear it.
- Subsequent
setVisible(false)taps re-trigger the same broken animation; the snackbar never goes away.
Repro
- New arch enabled.
- Mount a global
<Snackbar visible={visible} onDismiss={() => setVisible(false)} action={{ label: 'Action', onPress: () => {} }}>Message</Snackbar>. setVisible(true), thensetVisible(false).- Snackbar stays on screen.
Reproduced on:
- iOS 18 simulator (iPhone 15)
- iOS 26 simulator (iPhone 17 Pro Max)
- Android Pixel 8 emulator (API 35)
All with newArchEnabled: true.
Environment
react-native-paper: 5.15.2react-native: 0.83.6- Expo SDK 55
- Fabric / new arch: enabled
Proposed fix
Drop the if (finished) guard, mirroring how #4447 worked around the same class of Fabric noise on the show path:
Animated.timing(opacity, {
toValue: 0,
duration: 100 * scale,
useNativeDriver: true,
- }).start(({ finished }) => {
- if (finished) {
- setHidden(true);
- }
+ }).start(() => {
+ setHidden(true);
});
Trade-off
Under a genuine interrupt (a new show kicked off mid-hide), setHidden(true) would now also fire. The next render uses the new visible=true path → setHidden(false) → re-animates show. The visible artefact is at worst a one-frame snap. A stuck Snackbar that no state change can clear is strictly worse.
Happy to open a PR if useful. Tested locally via patch-package; resolves the issue on both platforms.
- Dominant language
- TypeScript
- Stars
- 14.5k
- Forks
- 2.2k
- Avg merge
- 5d 10h
- Merged PRs (30d)
- 10
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from callstack/react-native-paper
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
callstack/react-native-paper#5096 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
callstack/react-native-paper#5093 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
callstack/react-native-paper#5003 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
callstack/react-native-paper#4881 ·
-
feature request
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
callstack/react-native-paper#4863 · 1 comment ·
All issues in callstack/react-native-paper
Similar issues
-
VerificationGate: ATTRIBUTION quote guard never matches a normal quotation (\b around the quote) Open
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
danielmiessler/LifeOS#2234 ·
-
T: Bug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
-
Difficulty 1/5 Under an hour Newbie friendliness 85/100
-
Mend: dependency security vulnerability untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 70/100