react-native: Appearance addChangeListener handler is called when app goes to background with wrong color scheme
Description
A handler function of Appearance.addChangeListener
is triggered when the app goes to the background. It also has a wrong colorScheme
value.
React Native version:
System:
OS: macOS 10.15.1
CPU: (4) x64 Intel(R) Core(TM) i7-5557U CPU @ 3.10GHz
Memory: 92.24 MB / 16.00 GB
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 10.13.0 - /usr/local/bin/node
Yarn: 1.12.1 - /usr/local/bin/yarn
npm: 6.9.0 - /usr/local/bin/npm
Watchman: Not Found
Managers:
CocoaPods: 1.8.4 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
Android SDK:
API Levels: 23, 25, 26, 27, 28, 29
Build Tools: 27.0.3, 28.0.2, 28.0.3, 29.0.2
System Images: android-23 | Google APIs Intel x86 Atom, android-27 | Google Play Intel x86 Atom, android-28 | Google APIs Intel x86 Atom, android-28 | Google Play Intel x86 Atom, android-29 | Google APIs Intel x86 Atom
Android NDK: Not Found
IDEs:
Android Studio: 3.5 AI-191.8026.42.35.5791312
Xcode: 11.2.1/11B500 - /usr/bin/xcodebuild
Languages:
Python: 2.7.15 - /usr/local/bin/python
npmPackages:
@react-native-community/cli: Not Found
react: 16.11.0 => 16.11.0
react-native: 0.62.1 => 0.62.1
npmGlobalPackages:
*react-native*: Not Found
Steps To Reproduce
- Register
Appearance.addChangeListener
at the root of the app (I use it with react-native-navigation).
Appearance.addChangeListener(({ colorScheme }) => {
console.log(colorScheme);
});
- Move the app to the background.
Expected Results
No theme changed.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 47
- Comments: 47 (3 by maintainers)
Commits related to this issue
- Fix color scheme blink when bring app to front See facebook/react-native#28525 for more details. — committed to zhxie/conch-bay by zhxie a year ago
- Fix color scheme blink when bring app to front See facebook/react-native#28525 for more details. — committed to zhxie/conch-bay by zhxie a year ago
+1, having the same issue!
Dump question, isn’t it the easiest way to just call
Appearance.getColorScheme()
when the Listener fires? Works well for me without a cumbersome timer…Not stale
2 years passed and this bug still haunted me every other day
+1 The issue still persists in RN0.69+
@Macrow your workaround helped. thank you
here it is as a hook to use in lieu of the rn
useColorScheme
hook. I also usedsetTimeout
instead ofthrottle
The theme change in App Switcher is not applied immediately, and response is slow when entering foreground, but it is resolved.
But I want it to be solved in react-native.
Sorry, but as I say in the following link, it keeps happening very randomly with your workaround:
https://github.com/expo/expo/issues/10815#issuecomment-897325894
I have the same problem on iOS, and I found expo/react-native-appearance have this issue too, I don’t know if it was my mistake.
I fix it by
Lodash
temporary, I don’t find a better way.https://reactnative.dev/docs/usecolorscheme This hook could help someone.
The only way to 100.00% fix the flashing as of right now seems to be what @komik966 suggested in https://github.com/facebook/react-native/issues/28525#issuecomment-907805294: refactor every color with
DynamicColorIOS
, which I assume passes the color values for all appearances down to the OS and let the OS pick the right color value for the color mode, instead of listening for color mode changes and swapping the color in React Native.I have refactored my project with
DynamicColorIOS
and now the app also transitions very nicely when the color mode changes, but it requires a lot of additional work asDynamicColorIOS
is only supported in iOS and libraries like React Navigation also don’t fully support it (https://github.com/react-navigation/react-navigation/issues/10891), so such refactoring may not be practical for large complex projects.https://user-images.githubusercontent.com/31050761/193649332-f2211749-d1f7-461b-8a8a-1b474bdda38b.mp4
Definitely still seeing this. Moved to expo/react-native-appearance for now.
that’s great! Given that there are a couple of reports of the issue being fixed let’s close this. If you have any further issues I would recommend opening a new issue with a proper repro.
wow how is this bug still not fixed. i remember having this same bug in flutter, but there the issue was tagged, reproed, triaged, and fixed in less than 12 hours.
anyway, thanks for the many and varied workarounds.
this worked for me:
Experiencing flashing with useColorScheme hook as well…
“react-native”: “0.70.4”,
This is still happening in React Native 0.66.1. I’m not using any listeners, just the useColorScheme hook.
If I go to the device’s home screen and open the app again (without closing entirely), the app flashes for a second with dark appearance although the system scheme is set as light.
Results of my investigation:
This happens, because RN subscribes to changes inside
traitCollectionDidChange
. iOS toggles to both light and dark schemes to make light and dark snapshot of the application. More here: https://stackoverflow.com/a/63372828 It confirms @monomichael 's suggestion.https://github.com/facebook/react-native/blob/b51a99c73cc4fbcbb03c97f92b7f7f166493538f/React/CoreModules/RCTAppearance.mm#L120-L124
https://github.com/facebook/react-native/blob/b51a99c73cc4fbcbb03c97f92b7f7f166493538f/React/Base/RCTRootView.m#L363-L373
Here is described problem about invalid snapshot in app switcher https://stackoverflow.com/questions/60667186/is-there-any-method-to-achieve-true-dark-mode-in-react-native-for-ios
Conclusion:
Use
DynamicColorIOS
, it will:The problem is on iOS only. When backgrounding the app, perhaps due to a bug on iOS 13 the user interface style changes to the opposite color scheme and then back to the current color scheme immediately afterwards. The best solution is to debounce the notification calls by 10ms like they did on react-native-appearance.
This issue broke our Facebook login because we were rebooting the app to load dark mode theme mid login when the Facebook app took focus to do OAuth. Pretty difficult to troubleshoot.
This worked for me, just ignoring the argument passed into the function
I’m using version
0.73.4
(and finally so far) it seems to be working properly too 🙌My workaround (https://github.com/ds300/patch-package use for applying changes)
⚠️ PAY ATTENTION: These changes can create new bugs!
react-native+0.72.3.patch
2023, latest version, and this bug is still there. My (workaround) solution is using lodash.debounce with leading = false.
I solved it finally using AppState 🎉. Note: I am using NativeWind. Please adjust the code according to your needs.
Let me know if it doesn’t work!
@komik966 Very glad that you asked! I thought it would, and it almost did, but there were two minor cases where the
DynamicColorIOS
colors were not updated correctly in the app switcher, specifically:NativeBaseevery single NativeBase componentInput
andSelect
componentsNot sure ifI suspect that it might be becauseborderColor
s are being handled differently, since every instance ofborderColor
is not updating correctly but all my othercolor
s andbackgroundColor
s are being handled perfectly fine in both React Navigation and NativeBase.https://user-images.githubusercontent.com/31050761/193877709-07496d89-63e2-40e8-a407-c0b7c9d9859e.MP4
At the end, I chose to use the same color for the borders under both light and dark mode to avoid the flashing when going to the app switcher.
I started having this problem. The current version that is the problem is “react-native”:“0.66.4”, There was no such problem in version “react-native”: “0.64.2”,
Thanks @jasonaibrahim, I really didn’t want to fool with this nonsense today. That makes it easy! 🙌
With this code in my App.js, I am seeing the extra calls but not the flash back and forth between themes:
Hope that helps someone.
Here is a repo: https://github.com/rosskhanas/react-native-appearance-bug
Once the app goes to the background it logs 2 rows - 2 different values to the console -
light
, anddark
.