wix / wix/react-native-ui-lib

asBaseComponent: stale module-level colorScheme prevents re-render on scheme switch back

Open Beginner friendly
#3,945 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
TypeScript
Stars
7.2k
Forks
748
Avg merge
2d 18h
Merged PRs (30d)
1

Description

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
  • Components
  • Demo
  • Docs
  • Typings
Steps to reproduce
  1. App starts in light mode → module-level colorScheme is captured as 'light'
  2. Go to a settings/appearance screen and switch to dark mode → all RNUI components re-render correctly
  3. Navigate to any screen — new components mount during dark mode with state.colorScheme = 'light' (stale module-level value)
  4. Switch back to light mode → Scheme.broadcastSchemeChange('light') fires
  5. Stale components check 'light' !== 'light'falsesetState 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
  • Android
  • iOS
  • Web

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/commons/asBaseComponent.js and inspect how BaseComponent initializes its colorScheme state and registers appearanceListener. Reproduce the light-to-dark-to-light switch sequence with components mounted after the first change. Done means affected RNUI components re-render correctly in both directions without retaining stale colors.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, react-native
Domain
frontend, mobile-dev
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
85/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.