-
Notifications
You must be signed in to change notification settings - Fork 24.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[iOS] useColorScheme changes value when app is backgrounded #35972
Comments
I'm experiencing this same issue on React Native 0.67.4. My workaround for the time being to prevent screen flickering: const colorScheme = useColorScheme()
const [currentColorScheme, setCurrentColorScheme] = useState(colorScheme)
const onColorSchemeChange = useRef<NodeJS.Timeout>()
// Add a 1 second delay before switching color scheme
// Cancel if color scheme immediately switches back
useEffect(() => {
if (colorScheme !== currentColorScheme) {
onColorSchemeChange.current = setTimeout(() => setCurrentColorScheme(colorScheme), 1000)
} else if (onColorSchemeChange.current) {
clearTimeout(onColorSchemeChange.current)
}
}, [colorScheme])
// <App theme={currentColorScheme}> ... |
Here's my workaround avoiding the
|
any preview when this issue will be fixed? |
i am experiencing this one on 0.71.8 edit:after upgrade 0.72.3 it happens of release too. |
this hook might help, didn't test it tbh 😀 function useForegroundColorScheme() {
const colorScheme = useColorScheme()
const lastCorrectColorScheme = useRef(null)
if(!lastCorrectColorScheme.current) {
lastCorrectColorScheme.current = colorScheme
}
return React.useMemo(() => {
const appState = AppState.currentState
if(Platform.OS === 'ios' && appState.match(/inactive|background/)) {
return lasCorrectColorScheme.current
} else {
lastCorrectColorScheme.current = appState
return lastCorrectColorScheme.current
}
}, [colorScheme])
} |
|
This error happening to me in release build on iOS. Steps
React native 0.72.3 |
It happens on RN 0.72.0 too |
Experiencing this on 0.72.4, hermes enabled but without new architecture |
This is a result of the OS taking what is called a 'snapshot' on iOS, to facilitate the preview when you browse your open applications; a snapshot is required for both light & dark mode in case you change modes while on the open application screen, so the OS will report a brief moment in time both light & dark mode where the app should respond to these modes, or risk a flawed snapshot |
I've done a deeper investigation on that topic and it is the expected behavior of a native IOS application. OutcomesAs @mhaanstra-wearetriple mentioned it is called a "snapshot" that IOS will take when you go to the background. React native behaviourI've validated that mechanism and as you may see in the attached video this works correctly for native apps. HypothesisI've noticed that render on the JS side is done properly but the draw phase is not happening. Questions:
50-appearence-issue.mp4 |
Summary: Closes facebook#35972 Closes facebook#36713 This PR addresses a couple of issues with `useColorScheme` and the `Appearance` API. - facebook#38214 introduced a regression. Using to `RCTExecuteOnMainQueue` was a mistake as we need this to happen synchronously to return the result. Doing it async causes the `traitCollection` to remain uninitialized. - The `useColorScheme` hook is updating when the app is in the background on iOS and the OS is taking the snapshots for the app switcher. This causes a flash when returning to the app as the correct color is set again. Here, we can check for the app state in `traitCollectionDidChange` and not send these events when in the background. - Removed a line that was left over after some OS version checks were removed when support for iOS 12 was dropped. ## Changelog: [IOS] [FIXED] - Don't send the `RCTUserInterfaceStyleDidChangeNotification` when the app is in the background. Pull Request resolved: facebook#39439 Test Plan: Tested on `rn-tester`, logged the changes whenever `useColorScheme` updates. It no longer happens when the app is in the background. The returned interface style on the initial render is always correct now. Reviewed By: NickGerleman Differential Revision: D49454281 Pulled By: javache fbshipit-source-id: 87e24158a49c50608c79e73fb484442f5aad36a6
This is still an issue on 0.72.6, why was it closed? |
@salman-ar-sar Fix will be available in 0.73 based on changelog |
Oh okay. That's good to hear. Do we have an estimated timeline for the 0.73 release? |
yeah, I think I'm seeing something similar. when I bring it back it's redrawing the entire screen first in dark mode, then back to the light mode... |
"in case"? lol, seems very lazy and inefficient of the iOS developers here...wouldn't they know when the color scheme changes and only trigger a snapshot then? |
still exist on new version. using expo. RN 0.73 |
Why was this closed if it's still not fixed? |
Still not fixed :/ |
This is a terrible user experience - and still not fixed |
RN 0.74 and still not fixed 🥲 |
This reappears after upgrading to RN 0.76 with new arch enabled. |
The crappy thing is iOS doesn't even manage to take a snapshot of your app in both light and dark themes, since it's preventing JavaScript from doing a rerender until your app foregrounds again! So when you background your app and go change the system theme, then bring up the app switcher again, your app's snapshot is still in the old theme. It's a tough problem! For now the best solution seems to be to stop iOS taking two different snapshots by debouncing your system theme change listener. Not ideal but better than the default behaviour. |
+1 |
I am also having the same issue, does anybody know any solution , this is my code const updateTheme = (newTheme) => { useEffect(() => {
}, [theme.system, theme.bgChange, theme.mode]); |
@MihirP24 the solution provided by @ealmiladi above worked for me |
Hey followers! As of my research on this topic ReactNative 0.77.0 includes the modifications to fix this behaviour. It will be released next week. Release info: https://github.com/facebook/react-native/releases/tag/v0.77.0-rc.6 In my case a simple workaround just wasn't enough since I use react-native-ui-lib and it has it's own internal reference to |
Description
On a fresh
npx react-native init {appName}
project on iOS, if youconsole.log({isDarkMode})
and move the app to the background, you'll notice these sets of logs. It seems that theuseColorScheme
hook is reporting that the user's theme setting has been changed, although it hasn't changed at all. Bringing the app to the foreground again resolves the issue, but causes screen flickers on elements that rely on the value. This issue does not affect Android.Version
0.70.6 - 0.71.1
Output of
npx react-native info
System:
OS: macOS 12.5.1
CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Memory: 45.07 MB / 32.00 GB
Shell: 5.8.1 - /usr/local/bin/zsh
Binaries:
Node: 14.18.1 - ~/.nvm/versions/node/v14.18.1/bin/node
Yarn: 1.22.17 - /usr/local/bin/yarn
npm: 6.14.15 - ~/.nvm/versions/node/v14.18.1/bin/npm
Watchman: Not Found
Managers:
CocoaPods: 1.11.3 - /Users/ealimadi/.rvm/gems/ruby-2.7.5/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 22.1, iOS 16.1, macOS 13.0, tvOS 16.1, watchOS 9.1
Android SDK: Not Found
IDEs:
Android Studio: 2021.3 AI-213.7172.25.2113.9123335
Xcode: 14.1/14B47b - /usr/bin/xcodebuild
Languages:
Java: 11.0.13 - /usr/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: 18.1.0 => 18.1.0
react-native: 0.70.6 => 0.70.6
react-native-macos: Not Found
npmGlobalPackages:
react-native: Not Found
Steps to reproduce
Snack, code example, screenshot, or link to a repository
The text was updated successfully, but these errors were encountered: