feat: refactor snapshots when going back on Fabric
Description
PR refactoring snapshots when going back on Fabric on both platforms.
Hi @WoLewicki! While I was testing all examples from FabricTestExample, I've stumbled onto one app crash while being on the branch from this PR. When I'm trying to run Test640 and I'm coming back to the previous screen (from the screen with TouchableOpacities), I'm getting crash with exception AssertionException and IndexOutOfBoundsException. Do you know what might be the cause of this? 🤔
Exception from Logcat
2024-05-20 15:56:17.375 23934-23978 unknown:SoftAssertions com.fabrictestexample E Unhandled SoftException
com.facebook.react.bridge.AssertionException: Expected to run on UI thread!
at com.facebook.react.bridge.SoftAssertions.assertCondition(SoftAssertions.java:37)
at com.facebook.react.bridge.UiThreadUtil.assertOnUiThread(UiThreadUtil.java:44)
at com.facebook.react.fabric.FabricUIManager.resolveView(FabricUIManager.java:921)
at com.swmansion.rnscreens.NativeProxy.notifyScreenRemoved(NativeProxy.kt:26)
at com.facebook.jni.NativeRunnable.run(Native Method)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:233)
at java.lang.Thread.run(Thread.java:1012)
2024-05-20 15:56:17.420 23934-23934 AndroidRuntime com.fabrictestexample D Shutting down VM
2024-05-20 15:56:17.422 23934-23934 AndroidRuntime com.fabrictestexample E FATAL EXCEPTION: main
Process: com.fabrictestexample, PID: 23934
java.lang.IndexOutOfBoundsException: getChildDrawingOrder() returned invalid index 1 (child count is 1)
at android.view.ViewGroup.getAndVerifyPreorderedIndex(ViewGroup.java:2100)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4314)
at android.view.View.draw(View.java:23892)
at android.view.View.updateDisplayListIfDirty(View.java:22756)
at android.view.View.draw(View.java:23620)
at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:873)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4341)
at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:846)
at android.view.View.draw(View.java:23892)
at android.view.View.updateDisplayListIfDirty(View.java:22756)
at android.view.View.draw(View.java:23620)
at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4341)
at android.view.View.updateDisplayListIfDirty(View.java:22747)
at android.view.View.draw(View.java:23620)
at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
at androidx.coordinatorlayout.widget.CoordinatorLayout.drawChild(CoordinatorLayout.java:1312)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4317)
at android.view.View.updateDisplayListIfDirty(View.java:22747)
at android.view.View.draw(View.java:23620)
at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
at com.swmansion.rnscreens.ScreenStack.performDraw(ScreenStack.kt:315)
at com.swmansion.rnscreens.ScreenStack.access$performDraw(ScreenStack.kt:15)
at com.swmansion.rnscreens.ScreenStack$DrawingOp.draw(ScreenStack.kt:327)
at com.swmansion.rnscreens.ScreenStack.drawAndRelease(ScreenStack.kt:282)
at com.swmansion.rnscreens.ScreenStack.dispatchDraw(ScreenStack.kt:298)
at android.view.View.updateDisplayListIfDirty(View.java:22747)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4540)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4513)
at android.view.View.updateDisplayListIfDirty(View.java:22712)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4540)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4513)
at android.view.View.updateDisplayListIfDirty(View.java:22712)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4540)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4513)
at android.view.View.updateDisplayListIfDirty(View.java:22712)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4540)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4513)
at android.view.View.updateDisplayListIfDirty(View.java:22712)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4540)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4513)
at android.view.View.updateDisplayListIfDirty(View.java:22712)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4540)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4513)
at android.view.View.updateDisplayListIfDirty(View.java:22712)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4540)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4513)
at android.view.View.updateDisplayListIfDirty(View.java:22712)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:694)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:700)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:798)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:4939)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4643)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3822)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2465)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9305)
2024-05-20 15:56:17.422 23934-23934 AndroidRuntime com.fabrictestexample E at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1339)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1348)
at android.view.Choreographer.doCallbacks(Choreographer.java:952)
at android.view.Choreographer.doFrame(Choreographer.java:882)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1322)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8177)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
I used a slightly modified Test556 for testing my PR based on your changes. There is an error on android when navigating back with a custom headerTitle and headerRight:
Works fine when there's just one custom header element, works fine on iOS.
Repro code
import * as React from 'react';
import { Button, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerTitle: () => <Text>Simple Native Stack</Text>,
headerRight: () => <Text>Right</Text>,
}}>
<Stack.Screen name="First" component={First} />
<Stack.Screen name="Second" component={Second} />
</Stack.Navigator>
</NavigationContainer>
);
}
function First({ navigation }) {
return (
<Button
title="Tap me for second screen"
onPress={() => navigation.navigate('Second')}
/>
);
}
function Second({ navigation }) {
return (
<Button
title="Tap me for second screen"
onPress={() => navigation.popTo('First')}
/>
);
}
I can confirm the latest change fixes the issue I came upon 🎉