简体   繁体   English

重置主屏幕的导航堆栈(React Navigation 和 React Native)

[英]Resetting the navigation stack for the home screen (React Navigation and React Native)

I've got a problem with the navigation of React Navigation and React Native.我遇到了React Navigation和 React Native 的导航问题。 It is about resetting navigation and returning to the home screen.这是关于重置导航并返回主屏幕。

I've build a StackNavigator inside of a DrawerNavigator, and the navigation between home screen and other screens is working.我在 DrawerNavigator 中构建了一个 StackNavigator,并且主屏幕和其他屏幕之间的导航正常工作。 But the problem is, that the navigation stack grows and grows.但问题是,导航堆栈不断增长。 I'm not sure how to remove a screen from the stack.我不确定如何从堆栈中删除屏幕。

For example when going from the home screen to the settings screen, then to the entry screen and lastly again to the home screen, the home screen is twice in the stack.例如,当从主屏幕进入设置屏幕,然后进入条目屏幕,最后再次进入主屏幕时,主屏幕在堆栈中出现两次。 With the back button I do not get out of the app, but again to the entry screen.使用后退按钮,我不会退出应用程序,而是再次进入进入屏幕。

When selecting the home button again a reset of the stack would be great, but I don't know how to do this.再次选择主页按钮时,重置堆栈会很棒,但我不知道该怎么做。 Here someone tried to help an other person with a similar problem, but the solution didn't work for me. 在这里,有人试图帮助有类似问题的其他人,但该解决方案对我不起作用。

const Stack = StackNavigator({
  Home: {
    screen: Home
  },
  Entry: {
    screen: Entry
  },
  Settings: {
    screen: Settings
  }
})

export const Drawer = DrawerNavigator({
  Home: {
    screen: Stack
  }},
  {
    contentComponent: HamburgerMenu
  }
)

And this is a simple example of the drawer screen这是抽屉屏幕的一个简单示例

export default class HamburgerMenu extends Component {
  render () {
    return <ScrollView>
      <Icon.Button
        name={'home'}
        borderRadius={0}
        size={25}
        onPress={() => { this.props.navigation.navigate('Home')}}>
        <Text>{I18n.t('home')}</Text>
      </Icon.Button>

      <Icon.Button
        name={'settings'}
        borderRadius={0}
        size={25}
        onPress={() => { this.props.navigation.navigate('Settings')}}>
        <Text>{I18n.t('settings')}</Text>
      </Icon.Button>

      <Icon.Button
        name={'entry'}
        borderRadius={0}
        size={25}
        onPress={() => { this.props.navigation.navigate('Entry')}}>
        <Text>{I18n.t('entry')}</Text>
      </Icon.Button>
    </ScrollView>
  }
}

I hope you can help me.我希望你能帮助我。 This is an essential part of the navigation and a solution would be great!这是导航的重要组成部分,一个解决方案会很棒!

This is How I do it :这是我的做法:

reset(){
    return this.props
               .navigation
               .dispatch(NavigationActions.reset(
                 {
                    index: 0,
                    actions: [
                      NavigationActions.navigate({ routeName: 'Menu'})
                    ]
                  }));
  }

at least replace 'Menu' with 'Home'.至少将“菜单”替换为“主页”。 You may also want to adapt this.props.navigation to your implementation.您可能还想根据您的实现调整 this.props.navigation。

In version > 2 follow this:在版本 > 2 中,请遵循以下步骤:

import { NavigationActions, StackActions } from 'react-navigation';
        const resetAction = StackActions.reset({
                index: 0,
                actions: [NavigationActions.navigate({ routeName: 'MainActivity' })],
            });

this.props.navigation.dispatch(resetAction); 

React Navigation 5.x反应导航 5.x

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

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

Available in Snack零食

Here is how I do it:这是我如何做到的:

import { NavigationActions } from 'react-navigation'

this.props.navigation.dispatch(NavigationActions.reset({
    index: 0,
    key: null,
    actions: [NavigationActions.navigate({ routeName: 'ParentStackScreen' })]
}))

The important part is key: null .重要的部分是key: null

That wipes the stack while navigating from a child navigator to a parent navigator.这会在从子导航器导航到父导航器时擦除堆栈。

Do that if you get this error:如果出现此错误,请执行以下操作:

在此处输入图片说明

For animations, I use对于动画,我使用

// https://github.com/oblador/react-native-animatable
import * as Animatable from 'react-native-animatable'

I just control all the animations myself.我只是自己控制所有的动画。 Put them on any component you want by wrapping it with <Animatable.View> .通过用<Animatable.View>包裹它们,将它们放在您想要的任何组件上。

I found this way to go while using @react-navigation Bashirpour's Answer .我在使用@react-navigation Bashirpour's Answer时发现了这种方法。 However, while trying out Functional components where you already have navigation in props here is a neat way to write reset Stack action:但是,在尝试在props已经有导航的功能组件时,这里是一种编写重置堆栈操作的巧妙方法:

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

For newest versions of react-navigation you should use StackActions for reset the stack, here's a piece of code:对于最新版本的 react-navigation,您应该使用 StackActions 来重置堆栈,这是一段代码:

// import the following
import { NavigationActions, StackActions } from 'react-navigation'

// at some point in your code
resetStack = () => {
 this.props
   .navigation
   .dispatch(StackActions.reset({
     index: 0,
     actions: [
       NavigationActions.navigate({
         routeName: 'Home',
         params: { someParams: 'parameters goes here...' },
       }),
     ],
   }))
}

To use Back, you need to find the unique key associated with the path.要使用 Back,您需要找到与路径关联的唯一键。 Inside your navigation reducer, you can search the existing state to find the first route on the stack using that path, grab its key & pass that to Back.在您的导航减速器中,您可以搜索现有状态以使用该路径查找堆栈中的第一条路线,获取其密钥并将其传递给 Back。 Back will then navigate to the screen prior to the path you gave.然后返回将导航到您提供的路径之前的屏幕。

  let key;

  if (action.payload) {
    // find first key associated with the route
    const route = action.payload;

    const routeObj = state.routes.find( (r) => r.routeName === route );

    if (routeObj) {
      key = { key: routeObj.key };
    }
  }

  return AppNavigator.router.getStateForAction( NavigationActions.back( key ), state );

In React Navigation Versions 5.x在 React 导航版本 5.x 中

You can use StackActions.replace in this version您可以在此版本中使用StackActions.replace

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


navigation.dispatch(
    StackActions.replace('Home', { test: 'Test Params' })
)

Full Example: (Available in Snack )完整示例:(在零食中提供

import * as React from 'react';
import { View, Button, Text } from 'react-native';
import { NavigationContainer, StackActions } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

function SplashScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text style={{fontSize:25,marginBottom:25}} >SPLASH SCREEN!</Text>
      <Button
        title="Replace (RESET) with Home"
        onPress={() =>
          navigation.dispatch(
            StackActions.replace('Home', { test: 'Test Params' })
          )
        }
      />
      <View style={{margin:10}}/>
      <Button
        title="Push Home on the stack"
        onPress={() =>
          navigation.dispatch(StackActions.push('Home', { test: 'Test Params' }))
        }
      />
    </View>
  );
}

function HomeScreen({ navigation, route }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text style={{fontSize:25,marginBottom:25}}>Home Screen!</Text>

      <Text style={{margin:10}}>{route.params.test}</Text>

      <Button
        title="Push same screen on the stack"
        onPress={() => navigation.dispatch(StackActions.pop(1))} 
      /> 
      <View style={{margin:10}}/>
      <Button
        title="Pop one screen from stack" 
        onPress={() =>
          navigation.dispatch(StackActions.push('Home', { test: 'Test Params' }))
        }
      />
      <View style={{margin:10}}/>
      <Button
        title="Pop to top" 
        onPress={() => navigation.dispatch(StackActions.popToTop())}
      />
    </View>
  );
}

const Stack = createStackNavigator();

export default function App() { 
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Splash" component={SplashScreen} />
        <Stack.Screen name="Home" component={HomeScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

NavigationActions.reset() seems to be the preferable solution. NavigationActions.reset()似乎是更好的解决方案。 One issue I ran into with it actions was the tab buttons.我在操作中遇到的一个问题是选项卡按钮。 Tabs would still show even if I explicitly turned them off in component.即使我在组件中明确关闭了选项卡,它们仍会显示。 If I used navigation.navigate() instead of doing this via reset() it would work fine.如果我使用 navigation.navigate() 而不是通过reset()这样做,它会工作正常。

SomeComponentScreen.navigationOptions = {
  header: null
};

A workaround for this annoyance that worked for me is to consecutively call multiple navigate statements.对我有用的这种烦恼的解决方法是连续调用多个navigate语句。

      navigation.goBack();   // this would pop current item in stack
      navigation.navigate({
        routeName: 'SomeOtherComponent'
      });

The Answer is createSwitchNavigator , it those not stack up your navigation.答案是createSwitchNavigator ,它不会叠加您的导航。 Add your auth screen/navigator in a createSwitchNavigator with the home screen/stack.将您的身份验证屏幕/导航器添加到带有主屏幕/堆栈的 createSwitchNavigator 中。

With that, when you navigate from home to log in, the stacks are not kept.这样,当您从家中导航以登录时,不会保留堆栈。

For more on it https://reactnavigation.org/docs/en/auth-flow.htmlLoginStack有关更多信息https://reactnavigation.org/docs/en/auth-flow.htmlLoginStack

The pop action takes you back to a previous screen in the stack.弹出操作将您带回到堆栈中的前一个屏幕。 The n param allows you to specify how many screens to pop back by. n 参数允许您指定弹出的屏幕数量。

n - number - The number of screens to pop back by. n - number - 弹回的屏幕数量。

import { StackActions } from 'react-navigation';从“反应导航”导入 { StackActions };

const popAction = StackActions.pop({ n: 1, }); const popAction = StackActions.pop({ n: 1, });

this.props.navigation.dispatch(popAction); this.props.navigation.dispatch(popAction);

Just mix the two solutions given above and this will work just fine, basically we have to use StackActions and key: null.只需混合上面给出的两个解决方案,这将工作得很好,基本上我们必须使用 StackActions 和 key: null。 Without using StackActions, it was throwing some error不使用 StackActions,它抛出了一些错误

import { NavigationActions, StackActions } from 'react-navigation';
const resetHandler = () => {
        props.navigation.dispatch(StackActions.reset({
            index: 0,
            key: null,
            actions: [NavigationActions.navigate({ routeName: 'PatientDetails' })]
        }))
    };

This works fine as of now:到目前为止,这工作正常:

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

resetStack = () => {
        const navigateAction = NavigationActions.navigate({
            routeName: 'Home',

            params: {},

            action: NavigationActions.navigate({ routeName: 'Home' }),
        });

        props.navigation.dispatch(navigateAction);
    }

Found here in the docs: https://reactnavigation.org/docs/en/navigation-actions.html#reset在文档中找到: https : //reactnavigation.org/docs/en/navigation-actions.html#reset

In your StackNavigator and DrawerNavigator you have used Home as a key, and i think it has to be unique and that's why its creating the problem.在您的 StackNavigator 和 DrawerNavigator 中,您使用 Home 作为键,我认为它必须是独一无二的,这就是它产生问题的原因。 Can you please try replacing Home with Stack inside your DrawerNavigator.您能否尝试用 DrawerNavigator 中的 Stack 替换 Home。

Hope this will help :)希望这会有所帮助:)

React Navigation 6.x反应导航 6.x

You can use popToTop() action to reset your stack.您可以使用popToTop()操作来重置您的堆栈。 example:例子:

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

navigation.dispatch(StackActions.popToTop());

React-Navigation Docs: https://reactnavigation.org/docs/stack-actions/#poptotop反应导航文档: https ://reactnavigation.org/docs/stack-actions/#poptotop

This fixed the issue for me ( React Navigation 5.x )这为我解决了这个问题( React Navigation 5.x

import {NavigationActions} from 'react-navigation';

navigation.reset(
  [NavigationActions.navigate({routeName: 'Profile'})],
  0,
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM