【问题标题】:How to navigate to a screen on back button press in React navigation 5 stack navigator如何在 React 导航 5 堆栈导航器中按下后退按钮导航到屏幕
【发布时间】:2020-11-02 15:15:16
【问题描述】:

已经回答了许多类似的问题,但没有一个使用最新的 react-navigation 版本。 我想在按下后退按钮时从“文档”屏幕转到“主”屏幕。这是我尝试过的,但它不起作用。

<NavigationContainer>
  <Stack.Navigator initialRouteName="Home" screenOptions={{ headerShown : false }}>
    <Stack.Screen name="Home" component={Home} />
    <Stack.Screen name="Camera" component={CameraScreen} />
    <Stack.Screen name="Document" component={Document} options={{
      headerLeft: (props) => (<HeaderBackButton {...props} onPress={() => props.navigation.navigate("Home")}/>)
    }} />
  </Stack.Navigator>
</NavigationContainer>

编辑以获得更多说明:我的应用从“主页”开始,然后转到“相机”,然后转到“文档”。现在,当我按下手机的后退按钮时,我不想在“文档”处返回“相机”,而是直接返回“主页”。 根据文档,这是覆盖后退按钮的方法。

<Screen
  name="Home"
  component={HomeScreen}
  options={{
  headerLeft: (props) => (
   <HeaderBackButton
     {...props}
     onPress={() => {
       // Do something
     }}
   />
 ),

}}/>; 但我不知道如何使用上面的代码去“家”。所以我搜索了类似的问题,其中大多数都有navigationOptions 和其他东西。我尝试按照以下问题的答案进行操作。

import { HeaderBackButton } from 'react-navigation';
static navigationOptions = ({navigation}) => {
  return{
    headerLeft:(<HeaderBackButton onPress={()=>{navigation.navigate('A')}}/>)
}

} 所以是的,即使我使用 console.log,后退按钮也没有响应

【问题讨论】:

    标签: react-native react-navigation react-navigation-stack


    【解决方案1】:

    您可以使用导航“beforeRemove”事件自定义后退按钮的行为,该事件在卸载屏幕之前触发。

     useEffect(() => {
        const unsubscribe = navigation.addListener('beforeRemove', e => {
          e.preventDefault(); // Prevent default action
          unsubscribe() // Unsubscribe the event on first call to prevent infinite loop
          navigation.navigate('Home') // Navigate to your desired screen
        });
     }, [])
    

    这种方法的好处是它会触发任何类型的返回导航,无论是应用内返回按钮还是设备返回按钮/手势。

    Navigation Events Doc

    【讨论】:

      【解决方案2】:

      我设法实现了我所需要的。我不得不覆盖“文档”中的物理后退按钮。

       useFocusEffect(
              useCallback(() => {
                const onBackPress = () => {
                  navigation.pop(2); // remove two screens i.e. Document and Camera
                  return true // disable normal behaviour
                };
                BackHandler.addEventListener('hardwareBackPress', onBackPress); // detect back button press
                return () =>
                  BackHandler.removeEventListener('hardwareBackPress');
              }, [])
            );
      

      【讨论】:

        【解决方案3】:

        你试过CommonActions.reset吗?

        来自doc 的类似内容:

        import { CommonActions } from '@react-navigation/native';
        
        // when you want to navigate to the Documents page, instead of doing
        navigation.navigate({routeName: 'Documents'});
        
        // you can try
        navigation.dispatch(
          CommonActions.reset({
            index: 1,
            routes: [
              { name: 'Home' },
              {
                name: 'Documents',
                params: { name: 'abc' },
              },
            ],
          })
        );
        

        因此,当您从 Documents 返回时,您将前往堆栈中的上一个屏幕:Home

        【讨论】:

        • 我不明白如何将它与我的功能组件合并
        • 暗物质正在使用 ReactNavigation V5。
        • @GChevass 我也在传递参数。 navigation.navigate('Document', { name : 'abc' })
        • 我在答案中添加了一个参数
        • The action 'RESET' with payload {"index":1,"routes":[{"name":"Home"},{"name":"Documents","params":{"name":"New Doc 2020-7-13 19-48-58"}}]} was not handled by any navigator. 进入文档屏幕后立即收到此错误
        【解决方案4】:

        我不确定你的代码是如何工作的。

        - 你可以给我们更多信息。

        但值得在下面尝试。

        import {CommonActions} from '@react-navigation/native';
        
        props.navigation.dispatch(
           CommonActions.navigate({name: 'Home'}),
        );
        

        https://reactnavigation.org/docs/navigation-prop/#dispatch

        【讨论】:

        • 如果你想通过按钮进入Home屏幕,例如onPress={() =&gt; { props.navigation.dispatch ...}}