You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
FlatList: Pull to Refresh refresh controls are "freezed" after navigation.goBack() #41515
I have 2 screens inside same context, useEffect depend on both screens depend on the same state from common context.
When I update context state data on Screen 2, and goBack()to Screen 1, refresh controls for flatlist are just freezed and I need to pull it to make it disappear:
State with refreshingvalue if changing to false correctly.
My observations, it is happening only when I write logs, so they are showing in metro. In release build with logs turned off everything is working as expected.
Maybe communication with metro in async operation is breaking something.
I've been fighting this bug for years, and I just let Claude have a crack at it. The future is scary and impressive. Here's my fix for this now, for any who dare attempt it...
There are actually two separate bugs with similar symptoms, both caused by the refresh control being detached from the window while its screen is inactive. With react-native-screens, inactive bottom tabs and covered native-stack screens are detached.
Environment
Expo SDK 54, React Native 0.81.5, old architecture (newArchEnabled: false). Can't move to the new architecture yet because of problems with Reanimated scroll handlers.
react-native-screens ~4.16, @react-navigation/bottom-tabs 7 and native-stack 7
FlashList 1.7.6 wrapped with Animated.createAnimatedComponent, plus plain FlatLists. It isn't list-specific.
Built from source (not prebuilt RN core), tested on iOS 18.7.8
Bug 1: refresh ends while detached, spinner stuck forever
Repro: pull to refresh, then switch tabs or goBack() before the fetch finishes. JS sets refreshing={false} while the screen is inactive. When you return, the spinner is frozen, the content stays pushed down, and scrolling doesn't clear it.
Cause:endRefreshingProgrammatically returns early when !_hasMovedToWindow, but setRefreshing: has already set _currentRefreshingState = NO. Nothing replays the skipped endRefreshing when the control re-enters a window. JS state and UIKit state stay out of sync permanently.
Bug 2: idle control drawn as "pulled" after re-attach
Repro: open a screen whose list is still on its initial load, navigate away during the load, and return after it finishes. refreshing was never true, but a frozen spinner is visible. Unlike bug 1, scrolling clears it.
Cause: logging showed super.refreshing == NO and _currentRefreshingState == NO the whole time, and no valueChanged fired. UIKit was never refreshing. The scroll view's content inset changed during the initial load (from -50 to 48.3 in our case), and after the detach and re-attach, UIKit lays out the idle control as partially pulled. This looks like the issue #31024 fixed by calling endRefreshing in didMoveToWindow. That call isn't in the current didMoveToWindow, which only toggles _hasMovedToWindow.
Activity
github-actions commentedon Nov 16, 2023
huiqun922 commentedon Nov 18, 2023
+1 same isuues. when switch tab or back to desktop and return app.
screen loss of focus happens。
only iOS
cortinico commentedon Nov 22, 2023
Is this a regression from 0.72?
huiqun922 commentedon Nov 22, 2023
0.72.4
ivanignatiev commentedon Nov 22, 2023
My observations, it is happening only when I write logs, so they are showing in metro. In release build with logs turned off everything is working as expected.
Maybe communication with metro in async operation is breaking something.
cortinico commentedon Nov 23, 2023
@ivanignatiev can you try on 0.72 and confirm if the issue persists there or not?
huiqun922 commentedon Nov 30, 2023
@cortinico i have same issue on 0.72.1
Demo Repository: https://github.com/huiqun922/rn_nav.git
2023-11-30.14.24.28.mov
huanguolin commentedon Jun 4, 2024
same issue with 0.72.12
jdarshan5 commentedon Jun 3, 2025
+1
jsonxr commentedon Sep 16, 2025
Still issue on 0.81
JacobJaffe commentedon Oct 9, 2026
I've been fighting this bug for years, and I just let Claude have a crack at it. The future is scary and impressive. Here's my fix for this now, for any who dare attempt it...
There are actually two separate bugs with similar symptoms, both caused by the refresh control being detached from the window while its screen is inactive. With react-native-screens, inactive bottom tabs and covered native-stack screens are detached.
Environment
newArchEnabled: false). Can't move to the new architecture yet because of problems with Reanimated scroll handlers.Animated.createAnimatedComponent, plus plain FlatLists. It isn't list-specific.Bug 1: refresh ends while detached, spinner stuck forever
Repro: pull to refresh, then switch tabs or
goBack()before the fetch finishes. JS setsrefreshing={false}while the screen is inactive. When you return, the spinner is frozen, the content stays pushed down, and scrolling doesn't clear it.Cause:
endRefreshingProgrammaticallyreturns early when!_hasMovedToWindow, butsetRefreshing:has already set_currentRefreshingState = NO. Nothing replays the skippedendRefreshingwhen the control re-enters a window. JS state and UIKit state stay out of sync permanently.Bug 2: idle control drawn as "pulled" after re-attach
Repro: open a screen whose list is still on its initial load, navigate away during the load, and return after it finishes.
refreshingwas never true, but a frozen spinner is visible. Unlike bug 1, scrolling clears it.Cause: logging showed
super.refreshing == NOand_currentRefreshingState == NOthe whole time, and novalueChangedfired. UIKit was never refreshing. The scroll view's content inset changed during the initial load (from -50 to 48.3 in our case), and after the detach and re-attach, UIKit lays out the idle control as partially pulled. This looks like the issue #31024 fixed by callingendRefreshingindidMoveToWindow. That call isn't in the currentdidMoveToWindow, which only toggles_hasMovedToWindow.Fix (patch-package)
node_modules/react-native/React/Views/RefreshControl/RCTRefreshControl.mReconcile the two states one tick after the control re-attaches to a window: