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

オープン 初心者向け
#3,945 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@huytdps13400 がすでに取り組んでいます。

2026年10月4日 から。

  • #4013 @omribz156 による — マージされずにクローズ
  • #4045 @huytdps13400 による — オープン

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
85/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
停滞
技術スタック
javascript, react-native

調査の方向性

src/commons/asBaseComponent.js から始め、BaseComponent が colorScheme state をどのように初期化し、appearanceListener を登録するかを確認します。最初の変更後にマウントされたコンポーネントを含めて、light-to-dark-to-light の切り替えシーケンスを再現します。影響を受ける RNUI コンポーネントが両方向で正しく再レンダリングされ、古い色を保持しなければ完了です。

索引モデルが issue の本文から書いたものです。

説明

bug

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' → 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
  • Android
  • iOS
  • Web
主要言語
TypeScript
スター
7.2k
フォーク
749
平均マージ
29分
マージ済み PR(30日)
1

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

wix/react-native-ui-lib のほかの issue

wix/react-native-ui-lib の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。