【问题标题】:React Native Navigation override goBack() of header back button in Stack NavigatorReact Native Navigation 覆盖 Stack Navigator 中标题后退按钮的 goBack()
【发布时间】:2020-07-21 03:04:18
【问题描述】:

我想在本地自定义堆栈导航器中默认后退按钮的行为到一个屏幕。

在假设堆栈上有screen1|screen2的细节中,一旦按下按钮,我想将一些道具从screen2传递到screen1。

我花了很多时间阅读 React 导航文档,在互联网上搜索和编码,但我无法做到这一点。

来自文档

在某些情况下,您可能比通过上述选项更想自定义后退按钮,在这种情况下,您可以将 headerLeft 选项设置为将呈现的 React 元素 我知道这个问题与 headerRight 组件的 goBack() 函数有关。

我想用类似 navigation.navigate("previousScreen",{{..props}}) 的东西覆盖与 headerLeft 后退按钮相关的默认函数 goBack()。

而且(这非常重要!!)我想将此行为本地用于特定屏幕,而不是全局使用。

我尝试过类似的方法,但不起作用。

 export default function App(){
 return(
 <NavigationContainer>
  <Stack.Navigator>
    <Stack.Screen name="FirstScreen" component={FirstScreen}/>
    <Stack.Screen name="SecondScreen" component={SecondScreen} options={{headerLeft: () => (
        <HeaderBackButton
          onPress={() =>navigation.navigate("FirstScreen",{//stuff//})}
          title="Info"
          color="#fff"
        />
      ),}}/>
  </Stack.Navigator>
</NavigationContainer>
 )}

【问题讨论】:

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


    【解决方案1】:

    如果您使用的是 react navigation v5,您可以使用以下命令设置特定屏幕的行为:

    import { HeaderBackButton } from '@react-navigation/stack';
    
    ...
    options={{
              headerLeft: (props) => (
                <HeaderBackButton
                  {...props}
                  onPress={() => {
                    navigation.navigate('screenName');
                  }}
                />
              ),
            }}
    ...
    

    您也可以改为使用 screenOptions={{}} 设置为堆栈级别。

    “导航”和“路线”也可以在屏幕道具上使用。

    options={({ navigation, route }) =&gt; ({headerLeft: ...})

    【讨论】:

    • 这里如何访问导航对象?
    • 您将如何访问此处的导航?
    【解决方案2】:

    当组件挂载后,注册返回按钮按下监听器

    componentDidMount() {
        BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPressAndroid)
    }
    
    componentWillUnmount() {
        BackHandler.removeEventListener('hardwareBackPress', this.onBackButtonPressAndroid)
    }
    

    然后在函数中,可以检查和处理action,例如:

    onBackButtonPressAndroid = () => {
        // Check if the current screen is focused or a subscreen is perhaps
        if (this.props.navigation.isFocused()) {
            if (someCondition) {
                // Do a navigation to a custom screen, pass props here if needed
                this.props.navigation.navigate('search')
                return true
                // Return true if you want to tell react navigation you've handled the back press
            }
            else if (this.state.offsetTop > 10) {
                // Ex. for scrolling to top
                this.scrollToTop()
                this.setState({
                    offsetTop: 0,
                })
                return true
            }
        }
        // Return false if you want to tell react navigation you didn't handle the back press
        return false
    }
    

    【讨论】:

    • 我指的是标题返回按钮,而不是硬件按钮!谢谢
    【解决方案3】:

    尝试将navigationOptions 传递到特定屏幕:

    export default function App(){
     return(
     <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="FirstScreen" component={FirstScreen}/>
        <Stack.Screen name="SecondScreen" component={SecondScreen}
           navigationOptions: ({ navigation }) => ({ headerLeft: (<HeaderBackButton onPress={() => {}}/>)
        })}}/>
      </Stack.Navigator>
    </NavigationContainer>
     )}
    

    您可以在navigation 上指定它。 或者在Second screen,试试这个:

    class SecondScreen extends React.Component {
      static navigationOptions = {
        headerLeft: (
          <Button
            onPress={() => alert('This is a back button!')}
            title="Title"
            color="#fff"
          />
        ),
      };
    }
    

    【讨论】:

    • 我想覆盖默认标题返回按钮的行为,即标题左侧(不是右侧)。我希望这个覆盖本地到第二个屏幕!
    • 更新了答案。
    • 你好,如果我想在屏幕上指定导航选项(你展示的第二种方式),我需要在实际的堆栈导航器中做什么才能接受参数?
    • @DipanshKhandelwal 我们可以对整个堆栈使用 headerLeft 吗?你能给我一些示例代码的链接吗?
    • @Paritosh 是的,我们可以使用它。上面的代码工作得很好。