Remove SceneTracker module and its use in AppRegistry (#57417)

Summary:
Pull Request resolved: https://github.com/react/react-native/pull/57417

`SceneTracker` was a small helper in `Libraries/Utilities` that tracked the active navigation scene. It was only ever consumed through a deep import and was never part of the public API. This removes it from the React Native package and moves scene tracking to the application layer that actually depends on it.

As part of this, `AppRegistry.runApplication` no longer sets the active scene to the app key. To let the application layer preserve that behavior for surfaces launched by app key, `WrapperComponentProvider` now receives the app key as an optional second argument.

Changelog: [General][Breaking] - Remove the `SceneTracker` module from `Libraries/Utilities`, stop setting the active scene from `AppRegistry.runApplication`, and pass the app key as an optional second argument to `WrapperComponentProvider`

Reviewed By: huntie, javache

Differential Revision: D110471317

fbshipit-source-id: 28d44c74d2cff7926094959f26aa1ed0bf4be9ad
This commit is contained in:
Rubén Norte
2026-07-14 09:31:46 -07:00
committed by meta-codesync[bot]
parent 8ce269b28d
commit bbb5be9b41
6 changed files with 8 additions and 77 deletions
@@ -44,5 +44,6 @@ export type Registry = {
};
export type WrapperComponentProvider = (
appParameters: Object,
appKey?: string,
) => React.ComponentType<any>;
export type RootViewStyleProvider = (appParameters: Object) => ViewStyleProp;
@@ -22,7 +22,6 @@ import type {
WrapperComponentProvider,
} from './AppRegistry.flow';
import SceneTracker from '../Utilities/SceneTracker';
import DeprecatedPerformanceLoggerStub from './DeprecatedPerformanceLoggerStub';
import {coerceDisplayMode} from './DisplayMode';
import HeadlessJsTaskError from './HeadlessJsTaskError';
@@ -105,7 +104,8 @@ export function registerComponent(
initialProps: appParameters.initialProps,
rootTag: appParameters.rootTag,
WrapperComponent:
wrapperComponentProvider && wrapperComponentProvider(appParameters),
wrapperComponentProvider &&
wrapperComponentProvider(appParameters, appKey),
rootViewStyle:
rootViewStyleProvider && rootViewStyleProvider(appParameters),
isLogBox: appKey === 'LogBox',
@@ -212,7 +212,6 @@ export function runApplication(
"* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called.",
);
SceneTracker.setActiveScene({name: appKey});
runnables[appKey](appParameters, coerceDisplayMode(displayMode));
}
@@ -1,42 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
export type Scene = {name: string, [string]: unknown, ...};
let _listeners: Array<(scene: Scene) => void> = [];
let _activeScene: Scene = {name: 'default'};
const SceneTracker = {
setActiveScene(scene: Scene) {
_activeScene = scene;
_listeners.forEach(listener => listener(_activeScene));
},
getActiveScene(): Scene {
return _activeScene;
},
addActiveSceneChangedListener(callback: (scene: Scene) => void): {
remove: () => void,
...
} {
_listeners.push(callback);
return {
remove: () => {
_listeners = _listeners.filter(listener => callback !== listener);
},
};
},
};
export default SceneTracker;
@@ -1,28 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
const SceneTracker = require('../SceneTracker').default;
describe('setActiveScene', function () {
it('can handle multiple listeners and unsubscribe', function () {
const listeners = [jest.fn(), jest.fn(), jest.fn()];
const subscriptions = listeners.map(listener =>
SceneTracker.addActiveSceneChangedListener(listener),
);
subscriptions[1].remove();
const newScene = {name: 'scene1'};
SceneTracker.setActiveScene(newScene);
expect(listeners[0]).toBeCalledWith(newScene);
expect(listeners[1]).not.toBeCalled();
expect(listeners[2]).toBeCalledWith(newScene);
});
});
+4 -3
View File
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<0d6ccb57cc35f5518f7a83a709927f2f>>
* @generated SignedSource<<3c6e653165b5e8314aba1038abcadea2>>
*
* This file was generated by scripts/js-api/build-types/index.js.
*/
@@ -5698,6 +5698,7 @@ declare function Wrapper_default(
): React.ReactNode
declare type WrapperComponentProvider = (
appParameters: Object,
appKey?: string,
) => React.ComponentType<any>
export {
AccessibilityActionEvent, // a0d4daa0
@@ -5720,7 +5721,7 @@ export {
AndroidKeyboardEvent, // e03becc8
Animated, // 91a7b171
AppConfig, // 35c0ca70
AppRegistry, // 7ef8e53a
AppRegistry, // 1e8c5a00
AppState, // 12012be5
AppStateEvent, // 80f034c3
AppStateStatus, // 447e5ef2
@@ -6001,7 +6002,7 @@ export {
VirtualizedSectionList, // 9fd9cd61
VirtualizedSectionListInstance, // 12b706d5
VirtualizedSectionListProps, // 12a58a4f
WrapperComponentProvider, // 4b8c7962
WrapperComponentProvider, // 9ef54e61
codegenNativeCommands, // 628a7c0a
codegenNativeComponent, // 32a1bca6
findNodeHandle, // 93f80214
@@ -43,7 +43,7 @@ let _sampleRate = DEBUG ? 1 : null;
* samples (e.g. to log them), make sure to call `FillRateHelper.setSampleRate(0.0-1.0)`.
*
* Listeners and sample rate are global for all `VirtualizedList`s - typical usage will combine with
* `SceneTracker.getActiveScene` to determine the context of the events.
* the active scene/route to determine the context of the events.
*/
class FillRateHelper {
_anyBlankStartTime: ?number = null;