-
Notifications
You must be signed in to change notification settings - Fork 33
Description
Description
After upgrading from 1.2.2 to 1.6.0, useResolveClassNames('bg-background') returns empty on first render when the Tailwind CSS stylesheet is injected into <head> after CSSListener.initialize() runs.
Use Case
We use useResolveClassNames to read Tailwind color values and inject them into React Navigation's ThemeProvider. This lets us drive the navigator's background, border, and card colors from our Tailwind theme:
const { backgroundColor } = useResolveClassNames('bg-background')
const { borderTopColor: borderColor } = useResolveClassNames('border-border')
return {
...currentTheme,
colors: {
...currentTheme.colors,
...(backgroundColor ? { background: backgroundColor.toString() } : undefined),
...(borderColor ? { border: borderColor.toString() } : undefined),
},
}When useResolveClassNames returns empty, the navigator falls back to React Navigation's DefaultTheme.colors.background (rgb(242, 242, 242)). Since the theme provider never re-renders with the resolved value, the gray background persists.
Root Cause
The getWebStyles implementation changed between versions:
- 1.2.2: Sets
classNameon a dummy div, readsgetComputedStyle()directly. Always works because the browser resolves CSS regardless of when stylesheets load. - 1.6.0: Iterates
CSSListener.activeRulesto find matching rules, then reads computed properties only from those. IfCSSListener.initialize()runs before the CSS is injected into<head>, the rules are missed.
The MutationObserver does catch later additions, but scheduleInitialization uses requestIdleCallback (50ms timeout) — useResolveClassNames reads before that fires.
Expected Behavior
useResolveClassNames should return the correct resolved styles on first render, matching the 1.2.2 behavior.
Workaround
We hardcode the correct fallback colors in our theme definitions so the empty return is masked. The useResolveClassNames override still applies once CSSListener catches up.
Environment
- uniwind 1.6.0 (worked in 1.2.2)
- Expo SDK 55, Metro bundler
- Web (React Navigation + Expo Router)
- Typical Expo setup, no custom CSS injection timing
This issue was written by Claude Code on behalf of the developer.