在反应导航中禁用后退按钮

Disable back button in react navigation

我正在使用反应本机导航 (react-navigation) StackNavigator。 它从登录页面开始,贯穿应用程序的整个生命周期。我不想有返回选项,返回到登录屏幕。有谁知道如何在登录屏幕后将其隐藏在屏幕上? 顺便说一句,我还通过使用将其隐藏在登录屏幕中:

const MainStack = StackNavigator({
  Login: {
    screen: Login,
    navigationOptions: {
      title: "Login",
      header: {
        visible: false,
      },
    },
  },
  // ... other screens here
})

我自己找到的 ;) 添加:

  left: null,

禁用默认后退按钮。

const MainStack = StackNavigator({
  Login: {
    screen: Login,
    navigationOptions: {
      title: "Login",
      header: {
        visible: false,
      },
    },
  },
  FirstPage: {
    screen: FirstPage,
    navigationOptions: {
      title: "FirstPage",
      header: {
        left: null,
      }
    },
  },

您可以使用 left:null 隐藏后退按钮,但对于 android 设备,当用户按下后退按钮时它仍然能够返回。您需要重置导航状态并使用 left:null

隐藏按钮

这里是重置导航状态的文档:
https://reactnavigation.org/docs/navigation-actions#reset

此解决方案适用于 react-navigator 1.0.0-beta.7,但 left:null 不再适用于最新版本。

1) 要使后退按钮在 react-navigation v2 或更新版本中消失:

v2-v4:

navigationOptions:  {
    title: 'MyScreen',
    headerLeft: null
}

v5 或更高版本:

{     
    navigationOptions:  {
    title: 'MyScreen',
    headerLeft: ()=> null,
    // `headerLeft: undefined` should work too
    // `headerLeft: null` should work but could trigger a TS error
}

2) 如果要清理导航堆栈:

假设您在要从中导航的屏幕上:

如果您使用的是 react-navigation v5 或更高版本,您可以使用 navigation.resetCommonActions.reset:

 // Replace current navigation state with a new one,
 // index value will be the current active route:

navigation.reset({
  index: 0,
  routes: [{ name: 'Profile' }],
});

此处提供来源和更多信息:https://reactnavigation.org/docs/navigation-prop/#reset

或:

navigation.dispatch(
  CommonActions.reset({
    index: 1,
    routes: [
      { name: 'Home' },
      {
        name: 'Profile',
        params: { user: 'jane' },
      },
    ],
  })
);

此处提供来源和更多信息:https://reactnavigation.org/docs/navigation-actions/#reset

对于旧版本的反应导航:

v2-v4 使用 StackActions.reset(...)

import { StackActions, NavigationActions } from 'react-navigation';

const resetAction = StackActions.reset({
  index: 0, // <-- currect active route from actions array
  actions: [
    NavigationActions.navigate({ routeName: 'myRouteWithDisabledBackFunctionality' }),
  ],
});

this.props.navigation.dispatch(resetAction);

v1 使用 NavigationActions.reset

3) 对于 android,您还必须使用 BackHandler:

禁用硬件后退按钮

http://reactnative.dev/docs/backhandler.html

或者如果你想使用钩子:

https://github.com/react-native-community/hooks#usebackhandler

否则,如果导航堆栈为空,应用程序将在 android 按下硬件后退按钮时关闭。

其他来源:感谢在下方添加评论并帮助将此答案更新为 v5 的用户。

反应导航版本 >= 1.0.0-beta.9

navigationOptions:  {
   headerLeft: null
}

我们可以通过将 headerLeft 设置为 null 来修复它

static navigationOptions =({navigation}) => {
    return {
        title: 'Rechercher une ville',
        headerLeft: null,
    }  
}

我们需要将 gesturesEnabled 设置为 false,同时将 headerLeft 设置为 null。因为我们也可以通过滑动屏幕来返回。

navigationOptions:  {
   title: 'Title',
   headerLeft: null,
   gestureEnabled: false,
}

在最新版本 (v2) 中有效 headerLeft:null。您可以在控制器的 navigationOptions 中添加如下所示

static navigationOptions = {
    headerLeft: null,
};

您是否考虑过使用 this.props.navigation.replace( "HomeScreen" ) 而不是 this.props.navigation.navigate( "HomeScreen" )

这样你就不会向堆栈中添加任何东西。因此,如果在 Android 中按下后退按钮或在 IOS 中向右滑动屏幕,HomeScreen 将不会挥动任何要返回的内容。

更多信息查看Documentation。 当然,您可以通过在 navigationOptions

中设置 headerLeft: null 来隐藏后退按钮

对于最新版本的 React Navigation,即使您在某些情况下使用 null,它仍可能显示 "back" 已写入!

在您的 main app.js 的屏幕名称下进行此操作,或者直接转到您的 class 文件 并添加:-

static navigationOptions = {
   headerTitle:'Disable back Options',
   headerTitleStyle: {color:'white'},
   headerStyle: {backgroundColor:'black'},
   headerTintColor: 'red',
   headerForceInset: {vertical: 'never'},
   headerLeft: " "
}

SwitchNavigator 将是完成此任务的方法。 SwitchNavigator 重置默认路由并在调用 navigate 操作时卸载身份验证屏幕。

import { createSwitchNavigator, createStackNavigator, createAppContainer } from 'react-navigation';

// Implementation of HomeScreen, OtherScreen, SignInScreen, AuthLoadingScreen
// goes here.

const AppStack = createStackNavigator({ Home: HomeScreen, Other: OtherScreen });
const AuthStack = createStackNavigator({ SignIn: SignInScreen });

export default createAppContainer(createSwitchNavigator(
  {
    AuthLoading: AuthLoadingScreen,
    App: AppStack,
    Auth: AuthStack,
  },
  {
    initialRouteName: 'AuthLoading',
  }
));

用户进入 SignInScreen 并输入他们的凭据后,您将调用

this.props.navigation.navigate('App');

使用 React Native 的 BackHandler 对我有用。只需将这一行包含在您的 ComponentWillMount 中:

BackHandler.addEventListener('hardwareBackPress', function() {return true})

它将禁用 android 设备上的后退按钮。

我认为添加 headerLeft : null 很简单,我使用的是 react-native cli,所以这就是示例:

static navigationOptions = {
    headerLeft : null
};

对于 react-navigation 版本 4.x

navigationOptions: () => ({
      title: 'Configuration',
      headerBackTitle: null,
      headerLayoutPreset:'center',
      headerLeft: null
    })

处理这种情况的最佳选择是使用 React navigation 提供的 SwitchNavigator。 SwitchNavigator 的目的是一次只显示一个屏幕。默认情况下,它不处理返回操作,并且在您切换离开时将路由重置为默认状态。这正是身份验证流程中所需的行为。

这是一个典型的实现方式。

  1. 创建 2 个堆栈导航器:一个用于身份验证(登录、注册、忘记密码等),另一个用于主 APP
  2. 创建一个屏幕,您将在其中检查要显示的切换导航器的哪条路线(我通常通过检查令牌是否存储在异步存储中来在初始屏幕中检查此)

以上语句的代码实现

import { createAppContainer, createSwitchNavigator } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import HomeScreen from "./homeScreenPath" 
import OtherScreen from "./otherScreenPath"
import SignInScreen from "./SignInScreenPath" 
import SplashScreen from "./SplashScreenPath"

const AppStack = createStackNavigator({ Home: HomeScreen, Other: OtherScreen });

const AuthStack = createStackNavigator({ SignIn: SignInScreen });


export default createAppContainer(
  createSwitchNavigator(
    {
      Splash: SplashScreen,
      App: AppStack,
      Auth: AuthStack,
    },
    {
      initialRouteName: 'Splash',
    }
  )
);

现在在 SplashScreen 中,您将检查令牌并相应地导航

import React from 'react';
import {
  ActivityIndicator,
  AsyncStorage,
  StatusBar,
  StyleSheet,
  View,
} from 'react-native';

class SplashScreen extends React.Component {
  componentDidMount() {
    this.checkIfLogin();
  }

  // Fetch the token from storage then navigate to our appropriate place
  checkIfLogin = async () => {
    const userToken = await AsyncStorage.getItem('userToken');

    // This will switch to the App screen or Auth screen and this splash
    // screen will be unmounted and thrown away.
    this.props.navigation.navigate(userToken ? 'App' : 'Auth');
  };

  // Render any loading content that you like here
  render() {
    return (
      <View>
        <ActivityIndicator />
        <StatusBar barStyle="default" />
      </View>
    );
  }
}

Once you change routes in SwitchNavigator it removes the older route automatically and hence if you press the back button it will not take you to the auth/login screens anymore

简单做

headerLeft: null

在您阅读此答案时可能已弃用。 你应该使用以下

   navigationOptions = {
        headerTitle : "Title",
        headerLeft : () => {},
    }
headerLeft: null

这在最新的 React Native 版本中不起作用

应该是:

navigationOptions = {
 headerLeft:()=>{},
}

对于打字稿:

navigationOptions = {
 headerLeft:()=>{return null},
}

对于带有 Typescript 的最新版本 React Navigation 5:

<Stack.Screen
    name={Routes.Consultations}
    component={Consultations}
    options={{headerLeft: () => null}}
  />

ReactNavigation v 5.0 - 堆栈选项:

options={{
headerLeft: () => { 
 return <></>; 
}
}}

在 react-navigation 版本 5.x 中,你可以这样做:

import { CommonActions } from '@react-navigation/native';

navigation.dispatch(
  CommonActions.reset({
    index: 1,
    routes: [
      { name: 'Home' },
      {
        name: 'Profile',
        params: { user: 'jane' },
      },
    ],
  })
);

您可以阅读更多内容here

从 React Navigation v5.7 开始,文档中有一个新的官方解决方案:

https://reactnavigation.org/docs/preventing-going-back

使用 beforeRemove 作为导航侦听器以防止来自 Android 后退按钮、header 后退按钮和自定义后退操作的后退行为。

虽然提供了很好的答案,但我认为这很简单

    useEffect(() => {
    props.navigation.addListener("beforeRemove", (e) => {
      e.preventDefault();
    });
  }, [props.navigation]);

我正在使用 v6,它适合我:

 <Stack.Screen
    name="ApparelsHome"
    component={ApparelsHome}
    options={{
      headerLeft: () => <></>,
    }}
/>

如果你的反应导航v6.x

options={{
   title: "Detail Pembayaran",
   headerTitleStyle:{
      fontWeight:'bold',
   },
   headerBackVisible:false
}}

参考:React document

您也可以headerLeft:()=>false去掉后退按钮

<Stack.Screen name="ImageScreen" component={ShowImage} options={{title:"SMAART", headerLeft:()=>false}} />

对于 react-navigation V6.0

<Stack.Screen
          name={'Dashboard'}
          component={Dashboard}
          options={{
            gestureEnabled: false,
            headerShown: true,
            headerLeft: () => <></>,
          }}>
</Stack.Screen>
import React,{useEffect,useState,useRef} from 'react';
import { BackHandler,View } from 'react-native';

export default function App() {

  useEffect(() => {
    const backHandler = BackHandler.addEventListener('hardwareBackPress', () => true)
    return () => backHandler.remove()
  }, [])

return(
<View>

</View>
)}