From 314dcea3c46d9891695152c5cade57c02058cbc3 Mon Sep 17 00:00:00 2001 From: lazerg Date: Mon, 26 Oct 2026 11:03:12 +0500 Subject: [PATCH] Don't resume the new context without an Activity after a reload on Android --- .../facebook/react/runtime/ReactHostImpl.kt | 2 +- .../facebook/react/runtime/ReactHostTest.kt | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt index 117502ca0eaf..efe12982c18d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt @@ -1109,7 +1109,7 @@ public class ReactHostImpl( * Native is reloading, it seems reasonable to assume that: (1) We must have navigated to a * React Native screen in the past, or (2) We must be on a React Native screen. */ - if (isReloading && !isManagerResumed) { + if (isReloading && !isManagerResumed && currentActivity != null) { reactLifecycleStateManager.moveToOnHostResume(reactContext, currentActivity) } else { /** diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostTest.kt index 0d391a3725dc..e36969e4d300 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostTest.kt @@ -168,4 +168,38 @@ class ReactHostTest { reactHost.onHostDestroy(activityController.get()) assertThat(reactHost.lifecycleState).isEqualTo(LifecycleState.BEFORE_CREATE) } + + @Test + fun testActivityDestroyedDuringReload() { + val bgTasks = ArrayDeque() + reactHost = + spy( + ReactHostImpl( + activityController.get().application, + reactHostDelegate, + mock(), + { bgTasks.add(it) }, + Task.IMMEDIATE_EXECUTOR, + false /* allowPackagerServerAccess */, + false /* useDevSupport */, + ), + ) + doReturn(null).whenever(reactHost).getOrCreateReactHostInspectorTarget() + doNothing().whenever(reactHost).unregisterInstanceFromInspector(any()) + + reactHost.start() + while (bgTasks.isNotEmpty()) bgTasks.removeFirst().run() + reactHost.onHostResume(activityController.get()) + + reactHost.reload("Reload from testing infra") + reactHost.onHostPause(activityController.get()) + reactHost.onHostDestroy(activityController.get()) + while (bgTasks.isNotEmpty()) bgTasks.removeFirst().run() + assertThat(reactHost.lifecycleState).isEqualTo(LifecycleState.BEFORE_CREATE) + + val newActivity = Robolectric.buildActivity(Activity::class.java).create().start().resume() + reactHost.onHostResume(newActivity.get()) + val newReactContext = mockedBridgelessReactContextCtor.constructed().last() + verify(newReactContext).onHostResume(newActivity.get()) + } }