Repository navigation
Description
What happened?
Uniwind.setTheme('light') is called and Uniwind.currentTheme reports light, but every className resolves against the dark theme for the whole session. In production this happens on Android devices in system dark mode, on some cold starts.
| Actual | With the fix below |
|---|---|
Root cause: the theme is held in two places, and each reads Appearance.getColorScheme() on its own:
UniwindRuntime.currentThemeName(core/native/runtime.ts), read when the runtime module is evaluated. Expo's startup modules importreact-native, which Uniwind redirects to its components, so this happens before the app entry runs.#currentThemeinUniwindConfigBuilder(core/config/config.common.ts), read whenUniwindis first accessed, e.g. in the root layout.
The runtime is only updated in onThemeChange(), which runs when the config's theme changes. If the scheme changes between the two reads, they disagree and nothing reconciles them:
runtime.ts reads Appearance -> "dark"
scheme becomes "light"
config constructed, reads Appearance -> "light"
setTheme('light'): prevTheme === "light", onThemeChange() never runs
=> runtime.currentThemeName stays "dark"
On Android the scheme changes between the reads without any app code. The bundle starts evaluating before the Activity exists, so AppearanceModule.getColorScheme() falls back to the application context (system: dark). Then the Activity resumes with MODE_NIGHT_NO (userInterfaceStyle: "light") and reports light. The repro triggers the same ordering deterministically with Appearance.setColorScheme('light') in the entry file.
Suggested fix (verified in the repro), in src/core/config/config.native.ts:
constructor() {
super()
+ UniwindStore.runtime.currentThemeName = this.currentTheme
}An alternative is for runtime.ts to take its initial theme from the config instead of reading Appearance itself, so there is a single source of truth.
Steps to Reproduce
- Clone the repro and run
pnpm install. - Put the Android emulator in system dark mode.
- Run
pnpm android(Expo Go). - The screen shows
Uniwind.currentTheme: light, but with a black background and white text. Expected: white background, black text.
Snack or Repository Link
https://github.com/LouisHaftmann/uniwind-theme-race-repro
Uniwind version
1.13.1
React Native Version
0.88.1
Platforms
Android
Expo
Yes
Additional information 〰
- I've searched for similar issues in this repository and found none
Activity
github-actions commentedon Nov 5, 2026
New release v1.13.2 is published: https://github.com/uni-stack/uniwind/releases/tag/v1.13.2