Skip to content

Commit b9fafba

Browse files
fix(Android, Stack): dispatch lifecycle events when parent is not a ScreenFragment (#3854)
## Description <!-- Description and motivation for this PR. This section should include "what & why". Please link all related issues that merging this PR should close, by using the `Closes #<issue-number>` syntax. For example: Closes #12345. --> When React Native is loaded inside a `Fragment` (not directly in an `Activity`), for example in a brownfield setup using `ReactFragment`, lifecycle events are never dispatched for root screen fragments. This causes `transitionStart`/`transitionEnd` events in react-navigation to never fire. The root cause is in `ScreenFragment.dispatchViewAnimationEvent()`. The condition: ```kotlin if (parent == null || (parent is ScreenFragment && !parent.isTransitioning)) ``` does not account for the case where `parentFragment` is a regular `Fragment`. When RN runs inside a `ReactFragment`, `findFragmentManagerForReactRootView` returns that fragment's `childFragmentManager`. Root screen fragments then have `parentFragment` pointing to the host fragment. Since it's not `null` and not a `ScreenFragment`, the condition evaluated to `false` and all lifecycle events were silently dismissed. ## Changes <!-- This is "how" of the PR description. Please describe things you've changed here, make a **high level** overview, if change is simple you can omit this section. For example: - Updated `about.md` docs --> Added `parent !is ScreenFragment` to the condition in `ScreenFragment.dispatchViewAnimationEvent()`, so that lifecycle events are correctly dispatched when the parent fragment is not a `ScreenFragment` (e.g. `ReactFragment` in brownfield apps). Such parents don't participate in screen transitions, so they should be treated the same as `parent == null`. ## Before & after - visual documentation <!-- This section is MANDATORY for any PR that introduces any visual changes. If your PR does not introduce such changes, please omit this section. Consider using a table here to position the recordings / screenshots next to each other. | Before | After | | --- | --- | | https://github.com/user-attachments/assets/39dd7322-d741-4da8-b349-5820afbd5781 | https://github.com/user-attachments/assets/09246787-0be8-4488-9eb8-a28b72d9db72| Alternatively add two sections - Before & After ### Before ### After --> ### Before https://github.com/user-attachments/assets/39dd7322-d741-4da8-b349-5820afbd5781 ### After https://github.com/user-attachments/assets/09246787-0be8-4488-9eb8-a28b72d9db72 ## Test plan <!-- Please name all newly added and existing test files that you tested the changes with. This section should also contain short description of steps to reproduce the issue. The reproduction code should be minimal & complete. Don't exclude exports or remove "not important" parts of reproduction example. --> Reproducing this in FabricExample without adding a brownfield component is not possible. However, I tested all events in the example app after applying the change and everything works the same as before. ## Checklist - [x] Included code example that can be used to test this change. - [x] For visual changes, included screenshots / GIFs / recordings documenting the change. - [x] For API changes, updated relevant public types. - [x] Ensured that CI passes --------- Co-authored-by: Kacper Kafara <kacperkafara@gmail.com>
1 parent 7996731 commit b9fafba

1 file changed

Lines changed: 3 additions & 1 deletion

File tree

android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,10 @@ open class ScreenFragment :
292292
// since we subscribe to parent's animation start/end and dispatch events in child from there
293293
// check for `isTransitioning` should be enough since the child's animation should take only
294294
// 20ms due to always being `StackAnimation.NONE` when nested stack being pushed
295+
// When the parent is not a ScreenFragment (e.g. when RN is loaded inside a ReactFragment
296+
// in a brownfield setup), we always dispatch. Such parents don't participate in screen transitions.
295297
val parent = parentFragment
296-
if (parent == null || (parent is ScreenFragment && !parent.isTransitioning)) {
298+
if (parent == null || parent !is ScreenFragment || !parent.isTransitioning) {
297299
// onViewAnimationStart/End is triggered from View#onAnimationStart/End method of the fragment's root
298300
// view. We override an appropriate method of the StackFragment's
299301
// root view in order to achieve this.

0 commit comments

Comments
 (0)