React Native v5中navigation.goBack()导航至错误页面的技术问题咨询
你的导航问题根源出在导航对象的误用上:你在MainTabScreen里配置各个子页面的headerLeft时,用的是来自外层Drawer Navigator的navigation对象,而不是MainTab这个内部Stack Navigator自己的导航对象。这就导致goBack()是在Drawer的全局栈上执行,而不是MainTab内部的页面栈,所以才会跳回之前访问过的Profile Screen,而不是进入Chat Screen前的页面。
另外,抽屉里的Home图标点击后回到Chat Screen,是因为Drawer Navigator的每个Screen(比如HomeDrawer)对应的内部栈状态会被保留,当你从Profile回到HomeDrawer时,MainTab的栈还停留在之前的Chat Screen位置,没有重置到Home。
下面是具体的修改步骤,帮你修复这两个问题:
1. 修复MainTab内部页面的导航逻辑
修改MainTab.Screen的options配置,确保每个子页面使用自己所属的MainTab栈的navigation对象,而不是外层Drawer的:
const MainTab = createStackNavigator(); function MainTabScreen ({ navigation }) { // 这个navigation是外层Drawer的,仅用于HomeScreen的打开抽屉 return( <MainTab.Navigator screenOptions ={{ headerStyle:{ backgroundColor:"#009387" , }, gestureEnabled: false, headerTintColor: '#fff', headerTitleStyle: { fontWeight: 'bold', fontSize: height*0.023, textAlign: 'center', } }}> {/* HomeScreen保留外层navigation用于打开抽屉,没问题 */} <MainTab.Screen name = "Home" component={HomeScreen} options= {{ title: '', headerLeft: () => ( <Icon.Button name = "menu" size={25} backgroundColor= "#009387" onPress={ () => navigation.openDrawer()}> </Icon.Button> ), }}/> {/* 修改NextScreen的options,使用内部栈的navigation */} <MainTab.Screen name = "NextScreen" component={NextScreen} options={({ navigation }) => ({ title: i18n.t(''), headerLeft: () => ( <Icon.Button name = "arrow-left" size={25} backgroundColor= "#009387" onPress={ () => navigation.goBack()}/> ) })}/> <MainTab.Screen name = "OtherScreen" component={OtherScreen} options= {{ title: i18n.t('') , headerTintColor: '#fff', headerLeft: null, }}/> {/* 修改ChatScreen的options,使用内部栈的navigation */} <MainTab.Screen name = "ChatScreen" component={ChatScreen} options={({ navigation }) => ({ title: '' , headerTintColor: '#fff', headerLeft: ()=>( <Icon.Button name = "arrow-left" size={25} backgroundColor= "#009387" onPress={ () => navigation.goBack()}/> ) })}/> </MainTab.Navigator> )}
这里的关键是给options传递一个函数,函数参数里的navigation就是当前MainTab栈的导航对象,调用它的goBack()就会正确回到内部栈的上一页。
2. 修复抽屉Home图标跳转逻辑
修改DrawerContent里的Home按钮,确保点击时不仅回到HomeDrawer,还重置MainTab的栈到Home页面:
export function DrawerContent (props){ return( <Drawer.Section> <DrawerItem icon={({color, size }) => ( <Icon name="home-outline" color={color} size={height*0.032} /> )} label= {i18n.t('')} onPress={()=>{ // 跳转到HomeDrawer,并指定内部显示Home页面,重置栈 props.navigation.navigate('HomeDrawer', { screen: 'Home' }); }} /> <DrawerItem icon={({color, size }) => ( <Icon name="account-outline" color={color} size={height*0.032} /> )} label= {i18n.t('')} onPress={()=>{props.navigation.navigate('ProfileStackScreen')}} /> </Drawer.Section> ) }
如果上面的方式还不能完全重置栈(比如之前的历史还保留),可以改用reset方法彻底清空栈:
onPress={()=>{ props.navigation.reset({ index: 0, routes: [ { name: 'HomeDrawer', params: { screen: 'Home' } // 指定MainTab显示Home页面 } ] }); }}
修改后,你的导航流程会变成:Screen 1 => Screen 5 => Screen 1 => Screen 2 => Screen 4 => (goBack) Screen 2
完全符合你的预期,同时点击抽屉Home图标会直接回到Screen 1,不会再陷入循环。
内容的提问来源于stack exchange,提问作者MK_Pierce

