Nested Navigation and Logout function issue
Description
Getting error while i do reset the navigation from the custom sidebar who is in nested navigation and also that navigation has another nested navigations.
Here is my navigation codes. 1 App.tsx
return (
<GestureHandlerRootView>
<PaperProvider>
<RootSiblingParent>
<SafeAreaProvider>
<GlobalProvider>
<NavigationContainer>
<AuthStackNavigation />
</NavigationContainer>
</GlobalProvider>
</SafeAreaProvider>
</RootSiblingParent>
</PaperProvider>
</GestureHandlerRootView>
);
2 AuthStackNavigation.tsx
return (
<>
<StatusBar backgroundColor={Theme.colors.appColor} barStyle={'light-content'} />
<Stack.Navigator
initialRouteName={Constants.SPLASH_SCREEN}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
screenOptions={({navigation, route}) => ({})}>
<Stack.Screen name={Constants.LOGIN_SCREEN} component={LoginScreen} options={{headerShown: false}} />
<Stack.Screen name={Constants.REGISTER_SCREEN} component={RegisterScreen} options={{headerShown: false}} />
<Stack.Screen name={Constants.DRAWER_NAVIGATION} component={DrawerNavigation} options={{headerShown: false}} />
<Stack.Screen name={Constants.SPLASH_SCREEN} component={SplashScreen} options={{headerShown: false}} />
</Stack.Navigator>
</>
);
3 DrawerNavigation.tsx
const doLogout = () => {
navigation.reset({
index: 0,
routes: [{name: Constants.LOGIN_SCREEN}],
});
}
return (
<SafeAreaView style={{height: '100%', width: '100%'}}>
<StatusBar hidden={false} />
<Drawer.Navigator
drawerContent={(props) => <CustomSideBar {...props} currentScreen={currentScreen} onPress={doLogout} />}
screenOptions={{
headerShown: false,
drawerType: 'permanent', // Makes the drawer always visible
drawerStyle: {
width: drawerWidth, // Static width based on dimensions
},
swipeEnabled: false, // Disable swipe gestures to open/close
overlayColor: 'transparent', // Remove overlay
}}
initialRouteName={Constants.HOME_STACK_NAVIGATION}
>
<Drawer.Screen name={Constants.HOME_STACK_NAVIGATION} component={HomeStackNavigation} />
<Drawer.Screen name={Constants.SCHEDULE_STACK_NAVIGATION} component={ScheduleStackNavigation} />
<Drawer.Screen name={Constants.ENQUIRY_STACK_NAVIGATION} component={EnquiryStackNavigation} />
<Drawer.Screen name={Constants.VISIT_STACK_NAVIGATION} component={VisitStackNavigation} />
</Drawer.Navigator>
<Loader isLoading={globalContext.loading} />
</SafeAreaView>
);
Here is my library versions
"@react-navigation/drawer": "^7.3.12",
"@react-navigation/elements": "^2.4.2",
"@react-navigation/native": "^7.1.9",
"@react-navigation/native-stack": "^7.3.13",
"react": "18.3.1",
"react-native": "0.76.9",
"react-native-screens": "^4.10.0",
"react-native-safe-area-context": "^4.14.1",
"react-native-gesture-handler": "^2.25.0",
"react-native-reanimated": "^3.17.5",
"node": "v20.10.0",
"npm": "10.2.3"
Also It is only happening in android IOS works fine It should clear the navigation and go to login screen without any issue because we are just reseting the navigation.
Steps to reproduce
- Start the project
- Auth stack navigation will be called and shows the splash and then login screen
- Add the credentials and do login (you can modify for now to exclude the api call)
- Login will take user to DrawerNavigation
- user will do press on logout button from sidebar
- Error will be occurred and also only in android not in the iOS.
Snack or a link to a repository
https://github.com/ShRavan-Variya/Proctor.git
Screens version
4.10.0
React Native version
0.76.9
Platforms
Android
JavaScript runtime
None
Workflow
React Native (without Expo)
Architecture
None
Build type
Debug mode
Device
Android emulator
Device model
No response
Acknowledgements
Yes
Hi there! I tried to reproduce your problem, but without any luck. Below you can see reproduction that I used. Could you provide steps or change it, so I can see the problem? Please keep the changes as minimal as possible, preferably without expo.
import React from 'react';
import { NavigationContainer, useNavigation } from '@react-navigation/native';
import { createDrawerNavigator } from '@react-navigation/drawer';
import { Button, View, Text} from 'react-native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { CommonActions } from '@react-navigation/native';
import { SafeAreaView } from 'react-native-safe-area-context';
const Drawer = createDrawerNavigator()
const RootStack = createNativeStackNavigator();
const Home = () => {
const navigation = useNavigation();
return (
<SafeAreaView style={{flex: 1}}>
<Text>Splash</Text>
<Button onPress={() => navigation.navigate('Logged')} title='Go to logged' />
</SafeAreaView>
);
};
const Login = () => {
const navigation = useNavigation();
return (
<SafeAreaView style={{flex: 1}}>
<Text>Login</Text>
<Button onPress={() => navigation.navigate('Logged')} title='Go to logged'/>
</SafeAreaView>
);
};
const Screen = () => {
const navigation = useNavigation();
const resetAction = CommonActions.reset({
index: 0,
routes: [
{name: 'Login'},
],
});
return (
<View style={{flex: 1}}>
<Text>Test</Text>
<Button onPress={() => navigation.dispatch(resetAction)} title='Reset' />
</View>
);
};
const DrawerScreen = () => (
<Drawer.Navigator>
<Drawer.Screen name="A" component={Screen}/>
<Drawer.Screen name="B" component={Screen}/>
<Drawer.Screen name="C" component={Screen}/>
</Drawer.Navigator>
);
function App() {
return (
<NavigationContainer>
<RootStack.Navigator screenOptions={{headerShown: false}}>
<RootStack.Screen name="Splash" component={Home}/>
<RootStack.Screen name="Login" component={Login}/>
<RootStack.Screen name="Logged" component={DrawerScreen} />
</RootStack.Navigator>
</NavigationContainer>
);
}
export default App;
Same issue with RN 0.76.6 and "react-native-screens": "^4.9.1", it work with navigation.navigate("LoginScreen") but the issue is stack not getting clear, i tried replace, reset, dispatch, etc nothing is working
Hi @hmnz-tushar, could you provide minimal reproduction?
Also getting a ton of these in Sentry in production only, on Android since upgrading to rn new arch and screens 4.10.0.
I know this is not a minimal reproduction, but hoping that showing some additional stack traces from a real app helps the dev team. I do not use reanimated.
cc @maciekstosio
Let me know if i should create a separate issue.
"react-native-screens": "4.10.0",
"react-native": "0.77.2",
"@react-navigation/bottom-tabs": "7.3.3",
"@react-navigation/elements": "2.3.1",
"@react-navigation/native": "7.0.19",
"@react-navigation/native-stack": "7.3.3",
"@react-navigation/stack": "7.2.3",
IllegalStateException
The specified child already has a parent. You must call removeView() on the child's parent first.
mechanism
UncaughtExceptionHandler
handled
false
android.view.ViewGroup in addViewInner at line 5509
android.view.ViewGroup in addView at line 5328
android.view.ViewGroup in addView at line 5268
android.view.ViewGroup in addView at line 5240
com.swmansion.rnscreens.ScreenStackHeaderConfig in onUpdate at line 339
com.swmansion.rnscreens.ScreenStackHeaderConfig in onAttachedToWindow at line 156
android.view.View in dispatchAttachedToWindow at line 23227
android.view.ViewGroup in dispatchAttachedToWindow at line 3698
android.view.ViewGroup in dispatchAttachedToWindow at line 3705
1
android.view.ViewGroup in addViewInner at line 5552
android.view.ViewGroup in addView at line 5328
android.view.ViewGroup in addView at line 5268
androidx.fragment.app.FragmentStateManager in addViewToContainer at line 881
androidx.fragment.app.FragmentStateManager in createView at line 565
androidx.fragment.app.FragmentStateManager in moveToExpectedState at line 272
androidx.fragment.app.FragmentStore in moveToExpectedState at line 114
androidx.fragment.app.FragmentManager in moveToState at line 1455
androidx.fragment.app.FragmentManager in dispatchStateChange at line 3034
androidx.fragment.app.FragmentManager in dispatchViewCreated at line 2945
androidx.fragment.app.Fragment in performViewCreated at line 3148
androidx.fragment.app.FragmentStateManager in createView at line 588
androidx.fragment.app.FragmentStateManager in moveToExpectedState at line 272
androidx.fragment.app.FragmentManager in executeOpsTogether at line 1943
androidx.fragment.app.FragmentManager in removeRedundantOperationsAndExecute at line 1845
androidx.fragment.app.FragmentManager in execSingleAction at line 1751
androidx.fragment.app.BackStackRecord in commitNowAllowingStateLoss at line 323
com.swmansion.rnscreens.ScreenStack in onUpdate at line 306
com.swmansion.rnscreens.ScreenContainer in performUpdates at line 359
com.swmansion.rnscreens.ScreenContainer in onScreenChanged$lambda$7 at line 342
com.swmansion.rnscreens.ScreenContainer in $r8$lambda$BKP9nn15fXkNMeJuCPogdGvGxQY
com.swmansion.rnscreens.ScreenContainer$$ExternalSyntheticLambda0 in run
android.os.Handler in handleCallback at line 958
android.os.Handler in dispatchMessage at line 99
com.facebook.react.bridge.queue.MessageQueueThreadHandler in dispatchMessage at line 27
android.os.Looper in loopOnce at line 230
android.os.Looper in loop at line 319
android.app.ActivityThread in main at line 8919
java.lang.reflect.Method in invoke
com.android.internal.os.RuntimeInit$MethodAndArgsCaller in run at line 578
com.android.internal.os.ZygoteInit in main at line 1103
Hey @maciekstosio We have total 3 navigations 1 main root stack navigation as you have shown 2 drawer navigation inside the root stack navigation 3 stack navigation inside the drawer navigation
import React from 'react';
import { Button, Image, SafeAreaView, Text, TouchableOpacity, View } from 'react-native';
import { CommonActions, NavigationContainer, useNavigation } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createDrawerNavigator } from '@react-navigation/drawer';
const Drawer = createDrawerNavigator()
const RootStack = createNativeStackNavigator();
const Stack = createNativeStackNavigator();
const Home = () => {
const navigation = useNavigation();
return (
<SafeAreaView style={{flex: 1}}>
<Text>Splash</Text>
<Button onPress={() => navigation.navigate('Logged')} title='Go to logged' />
</SafeAreaView>
);
};
const Login = () => {
const navigation = useNavigation();
return (
<SafeAreaView style={{flex: 1}}>
<Text>Login</Text>
<Button onPress={() => navigation.navigate('Logged')} title='Go to logged'/>
</SafeAreaView>
);
};
const Screen = () => {
return (
<View style={{flex: 1}}>
<Text>Test</Text>
</View>
);
};
const StackNavigation = () => (
<Stack.Navigator>
<Stack.Screen name="A" component={Screen}/>
<Stack.Screen name="B" component={Screen}/>
<Stack.Screen name="C" component={Screen}/>
</Stack.Navigator>
);
const CustomSideBar = () => {
return (
<View style={{flex: 1}}>
<TouchableOpacity onPress={props.onPress}>
<Image source={'LOGOUT IMAGE URL'} resizeMode={'contain'} style={{height: 25, width: 25} />
<Text style={styles.textLogout}>{'Log Out'}</Text>
</TouchableOpacity>
</View>
);
};
const DrawerScreen = () => {
const navigation = useNavigation();
const doLogout = () => {
const resetAction = CommonActions.reset({
index: 0,
routes: [
{name: 'Login'},
],
});
}
return (
<Drawer.Navigator>
<Drawer.Navigator
drawerContent={(props) => <CustomSideBar {...props} onPress={doLogout} />}
screenOptions={{
headerShown: false,
drawerType: 'permanent',
drawerStyle: {width: drawerWidth},
swipeEnabled: false,
overlayColor: 'transparent',
}}
initialRouteName={"StackNavigationA"}
>
<Drawer.Screen name="StackNavigationA" component={StackNavigation}/>
<Drawer.Screen name="StackNavigationB" component={StackNavigation}/>
<Drawer.Screen name="StackNavigationC" component={StackNavigation}/>
</Drawer.Navigator>
)
};
function App() {
return (
<NavigationContainer>
<RootStack.Navigator screenOptions={{headerShown: false}}>
<RootStack.Screen name="Splash" component={Home}/>
<RootStack.Screen name="Login" component={Login}/>
<RootStack.Screen name="Logged" component={DrawerScreen} />
</RootStack.Navigator>
</NavigationContainer>
);
}
export default App;
I have similar structure and it is having that issue when i do logout form the custom sidebar from drawer
I went through our old issues, and found something that looks like the same problem: https://github.com/software-mansion/react-native-screens/issues/2491.
Seems like it was fixed in RN https://github.com/software-mansion/react-native-screens/issues/2491#issuecomment-2705817633 from 0.78, you can see the commit here: https://github.com/facebook/react-native/commit/f402ed17fa6d75aea24e2ad99a8b8d8ad20840e3
Okay, then what is the final solution on this version because they showcase other versions but not working on other versions. @maciekstosio
Getting the same issue, with RN0.79.3, react-native-screens 4.11.1, and following for react-navigation
"@react-navigation/drawer": "^7.4.1",
"@react-navigation/material-top-tabs": "^7.2.14",
"@react-navigation/native": "^7.1.10",
"@react-navigation/native-stack": "^7.3.14",
"@react-navigation/stack": "^7.3.3",
I have a pretty complicated navigation too (native stack => drawer => tabs) I'm also getting random crash while navigating from main screens (but not sure which one of the navigation type triggers it):
addViewAt: failed to insert view index=8 count=5
Got the same issue with RN 0.97 on Android.
It seems like there's a concurrency issue, when doing a navigation reset and directly a replace navigation it causes this error. When delaying the next action a few ms it doesn't happen.
Unhandled SoftException
com.facebook.react.bridge.ReactNoCrashSoftException: raiseSoftException(getOrCreateDestroyTask()): handleHostException(message = "Exception thrown when executing UIFrameGuarded")
at com.facebook.react.runtime.ReactHostImpl.raiseSoftException(ReactHostImpl.java:1025)
at com.facebook.react.runtime.ReactHostImpl.getOrCreateDestroyTask(ReactHostImpl.java:1625)
at com.facebook.react.runtime.ReactHostImpl.lambda$destroy$7(ReactHostImpl.java:615)
at com.facebook.react.runtime.ReactHostImpl.$r8$lambda$uso21_D6dCZdcf-JomVD56kdG4c(Unknown Source:0)
at com.facebook.react.runtime.ReactHostImpl$$ExternalSyntheticLambda35.call(D8$$SyntheticClass:0)
at com.facebook.react.runtime.internal.bolts.Task$2.run(Task.java:240)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at java.lang.Thread.run(Thread.java:1012)
Caused by: java.lang.RuntimeException: Exception thrown when executing UIFrameGuarded
at com.facebook.react.fabric.FabricUIManager$DispatchUIFrameCallback.doFrameGuarded(FabricUIManager.java:1400)
at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.kt:25)
at com.facebook.react.modules.core.ReactChoreographer.frameCallback$lambda$1(ReactChoreographer.kt:59)
at com.facebook.react.modules.core.ReactChoreographer.$r8$lambda$nSkFhrr5T7rop_XKwzlLov4NLLw(Unknown Source:0)
at com.facebook.react.modules.core.ReactChoreographer$$ExternalSyntheticLambda0.doFrame(D8$$SyntheticClass:0)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1348)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1359)
at android.view.Choreographer.doCallbacks(Choreographer.java:963)
at android.view.Choreographer.doFrame(Choreographer.java:888)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1333)
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:8223)
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:977)
Caused by: java.lang.IllegalStateException: addViewAt: failed to insert view [386] into parent [396] at index 0
at com.facebook.react.fabric.mounting.SurfaceMountingManager.addViewAt(SurfaceMountingManager.java:411)
at com.facebook.react.fabric.mounting.mountitems.IntBufferBatchMountItem.execute(IntBufferBatchMountItem.java:141)
at com.facebook.react.fabric.mounting.MountItemDispatcher.executeOrEnqueue(MountItemDispatcher.java:370)
at com.facebook.react.fabric.mounting.MountItemDispatcher.dispatchMountItems(MountItemDispatcher.java:265)
at com.facebook.react.fabric.mounting.MountItemDispatcher.tryDispatchMountItems(MountItemDispatcher.java:122)
at com.facebook.react.fabric.FabricUIManager$DispatchUIFrameCallback.doFrameGuarded(FabricUIManager.java:1396)
at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.kt:25)
at com.facebook.react.modules.core.ReactChoreographer.frameCallback$lambda$1(ReactChoreographer.kt:59)
at com.facebook.react.modules.core.ReactChoreographer.$r8$lambda$nSkFhrr5T7rop_XKwzlLov4NLLw(Unknown Source:0)
at com.facebook.react.modules.core.ReactChoreographer$$ExternalSyntheticLambda0.doFrame(D8$$SyntheticClass:0)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1348)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1359)
at android.view.Choreographer.doCallbacks(Choreographer.java:963)
at android.view.Choreographer.doFrame(Choreographer.java:888)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1333)
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:8223)
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:977)
Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:5281)
at android.view.ViewGroup.addView(ViewGroup.java:5110)
at android.view.ViewGroup.addView(ViewGroup.java:5050)
at android.view.ViewGroup.addView(ViewGroup.java:5022)
at com.swmansion.rnscreens.ScreenStackHeaderConfig.onUpdate(ScreenStackHeaderConfig.kt:339)
at com.swmansion.rnscreens.ScreenStackHeaderConfig.onAttachedToWindow(ScreenStackHeaderConfig.kt:156)
at android.view.View.dispatchAttachedToWindow(View.java:21991)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3496)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3503)
The issue is solved with the "react-native": "0.77.0" We have to update the related libraries for navigation, reanimated and screens for that and it will be cleared.
my updated libs are as below and it's working fine now.
"@react-navigation/drawer": "^7.5.8",
"@react-navigation/elements": "^2.6.4",
"@react-navigation/native": "^7.1.17",
"@react-navigation/native-stack": "^7.3.26",
"react": "18.3.1",
"react-native": "0.77.0",
"react-native-screens": "^4.16.0",
"react-native-safe-area-context": "^4.14.1",
"react-native-gesture-handler": "^2.21.2",
"react-native-reanimated": "3.17.1",
"node": "v20.10.0",
"npm": "10.2.3"
The issue is solved with the "react-native": "0.77.0" We have to update the related libraries for navigation, reanimated and screens for that and it will be cleared.
my updated libs are as below and it's working fine now.
"@react-navigation/drawer": "^7.5.8", "@react-navigation/elements": "^2.6.4", "@react-navigation/native": "^7.1.17", "@react-navigation/native-stack": "^7.3.26", "react": "18.3.1", "react-native": "0.77.0", "react-native-screens": "^4.16.0", "react-native-safe-area-context": "^4.14.1", "react-native-gesture-handler": "^2.21.2", "react-native-reanimated": "3.17.1", "node": "v20.10.0", "npm": "10.2.3"
Works for me. I upgraded the following libs:
- react-native-screens to 4.16.0
- react-navigation/bottom-tabs to 6.5.11