Skip to content

Commit 555fee2

Browse files
committed
fix(scatterlab): make StatusBar.currentHeight a lazy getter
As a class field the native constant is read while the module is being loaded. Under the New Architecture the TurboModule constants are only valid once the module instance exists, so on Android that read fails during startup and takes the app down with TypeError: Cannot read property 'HEIGHT' of undefined `import {StatusBar} from 'react-native'` alone is enough to trigger it — that is how @react-navigation/native-stack uses it, so an app crashes before its first screen even though it never touches StatusBar itself. Upstream closed the same report as not planned (react#41663). A getter defers the read to the point where the value is used. The JS spec wrapper does not cache a failed lookup, so a later read still returns the real height.
1 parent 291b330 commit 555fee2

3 files changed

Lines changed: 25 additions & 4 deletions

File tree

.github/scatterlab/allowed-tarball-diff.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,13 @@ scripts/cocoapods/rndependencies.rb
1111
Libraries/Text/TextInput/Multiline/RCTUITextView.mm
1212
Libraries/Text/TextInput/Singleline/RCTUITextField.mm
1313
React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm
14+
15+
# `StatusBar.currentHeight` as a lazy getter instead of a class field, see
16+
# https://github.com/react/react-native/issues/41663. Under the New Architecture the
17+
# TurboModule constants are only valid once the module instance exists, so evaluating
18+
# them while this module is being loaded crashes the app on Android - and `import
19+
# {StatusBar} from 'react-native'` alone is enough to trigger it (that is how
20+
# @react-navigation/native-stack uses it). The .d.ts is generated from the Flow source
21+
# at build time, so it differs as well.
22+
Libraries/Components/StatusBar/StatusBar.js
23+
types_generated/Libraries/Components/StatusBar/StatusBar.d.ts

packages/react-native/Libraries/Components/StatusBar/StatusBar.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,21 @@ class StatusBar extends React.Component<StatusBarProps> {
249249
*
250250
* @platform android
251251
*/
252-
static currentHeight: ?number =
253-
Platform.OS === 'android'
254-
? NativeStatusBarManagerAndroid.getConstants().HEIGHT
252+
// A class field would read the native constant while this module is being loaded.
253+
// Under the New Architecture the TurboModule constants are only valid once the module
254+
// instance exists, so that read crashes the app on Android during startup — and
255+
// `import {StatusBar} from 'react-native'` alone is enough to trigger it (that is how
256+
// @react-navigation/native-stack uses it). See
257+
// https://github.com/react/react-native/issues/41663.
258+
//
259+
// As a getter this is evaluated when the value is actually read. The JS spec wrapper
260+
// does not cache a failed lookup, so a later read still returns the real height; the
261+
// optional chaining covers callers that read in between.
262+
static get currentHeight(): ?number {
263+
return Platform.OS === 'android'
264+
? NativeStatusBarManagerAndroid.getConstants()?.HEIGHT
255265
: null;
266+
}
256267

257268
// Provide an imperative API as static functions of the component.
258269
// See the corresponding prop for more detail.

packages/react-native/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@scatterlab/react-native",
33
"name": "@scatterlab/react-native",
4-
"version": "0.87.0-scatterlab.0",
4+
"version": "0.87.0-scatterlab.1",
55
"description": "A framework for building native apps using React",
66
"license": "MIT",
77
"publishConfig": {

0 commit comments

Comments
 (0)