Description
asBaseComponent HOC captures colorScheme as a module-level constant at import time. Since BaseComponent extends React.PureComponent (via UIComponent), components mounted after a scheme change hold a stale state.colorScheme that matches the original scheme. When switching back to that original scheme, the appearanceListener guard (this.state.colorScheme !== colorScheme) evaluates to false, skipping setState and preventing re-render.
Related to
Steps to reproduce
- App starts in light mode → module-level
colorScheme is captured as 'light'
- Go to a settings/appearance screen and switch to dark mode → all RNUI components re-render correctly
- Navigate to any screen — new components mount during dark mode with
state.colorScheme = 'light' (stale module-level value)
- Switch back to light mode →
Scheme.broadcastSchemeChange('light') fires
- Stale components check
'light' !== 'light' → false → setState is never called → no re-render
Expected behavior
All RNUI components (Text, View, Button, Switch, etc.) should re-render with the updated color scheme when switching in both directions (light → dark AND dark → light).
Actual behavior
Components mounted after the first scheme change do not re-render when switching back to the original scheme. They retain the previous scheme's colors (e.g., light gray text on a light background) because BaseComponent (a PureComponent) skips rendering — both props and state appear unchanged.
More Info
Code snippet
The bug is in src/commons/asBaseComponent.js:
// Line 8 — evaluated ONCE at module load, never updated
const colorScheme = Scheme.getSchemeType();
function asBaseComponent(WrappedComponent, options = {}) {
// BaseComponent extends UIComponent which extends React.PureComponent
class BaseComponent extends UIComponent {
state = {
error: false,
colorScheme // All instances get the stale module-level value
};
appearanceListener = colorScheme => {
// This guard fails for stale instances when switching back to the original scheme
if (this.state.colorScheme !== colorScheme) {
this.setState({ colorScheme });
}
};
}
}
Fix — evaluate Scheme.getSchemeType() per instance instead of once at module level:
const EMPTY_MODIFIERS = {};
-const colorScheme = Scheme.getSchemeType();
function asBaseComponent(WrappedComponent, options = {}) {
class BaseComponent extends UIComponent {
state = {
error: false,
- colorScheme
+ colorScheme: Scheme.getSchemeType()
};
Screenshots/Video
N/A — the visual symptom is dark-theme text colors (e.g., #C9D6DF) rendered on a light-theme background (#F0F5F9), causing text to blend/disappear.
Environment
- React Native version: 0.83
- React Native UI Lib version: 8.3.4
Affected platforms
Description
asBaseComponentHOC capturescolorSchemeas a module-level constant at import time. SinceBaseComponentextendsReact.PureComponent(viaUIComponent), components mounted after a scheme change hold a stalestate.colorSchemethat matches the original scheme. When switching back to that original scheme, theappearanceListenerguard (this.state.colorScheme !== colorScheme) evaluates tofalse, skippingsetStateand preventing re-render.Related to
Steps to reproduce
colorSchemeis captured as'light'state.colorScheme = 'light'(stale module-level value)Scheme.broadcastSchemeChange('light')fires'light' !== 'light'→false→setStateis never called → no re-renderExpected behavior
All RNUI components (Text, View, Button, Switch, etc.) should re-render with the updated color scheme when switching in both directions (light → dark AND dark → light).
Actual behavior
Components mounted after the first scheme change do not re-render when switching back to the original scheme. They retain the previous scheme's colors (e.g., light gray text on a light background) because
BaseComponent(aPureComponent) skips rendering — both props and state appear unchanged.More Info
Code snippet
The bug is in
src/commons/asBaseComponent.js:Fix — evaluate
Scheme.getSchemeType()per instance instead of once at module level:const EMPTY_MODIFIERS = {}; -const colorScheme = Scheme.getSchemeType(); function asBaseComponent(WrappedComponent, options = {}) { class BaseComponent extends UIComponent { state = { error: false, - colorScheme + colorScheme: Scheme.getSchemeType() };Screenshots/Video
N/A — the visual symptom is dark-theme text colors (e.g.,
#C9D6DF) rendered on a light-theme background (#F0F5F9), causing text to blend/disappear.Environment
Affected platforms