为主屏幕重置导航堆栈(React 导航和 React 本机)

我有一个问题与导航 反应式导航和反应本机。它是关于重置导航和返回到主屏幕。

我已经在 DrawerNavigator 内部构建了一个 StackNavigator,主屏幕和其他屏幕之间的导航正在工作。但问题是,导航栈不断增长。我不确定如何从堆栈中删除屏幕。

例如,当从主屏幕到设置屏幕,然后到输入屏幕,最后再到主屏幕时,主屏幕在堆栈中出现了两次。有了后退按钮,我没有离开应用程序,而是再次进入屏幕。

当再次选择主页按钮时,重新设置堆栈会很棒,但我不知道如何做到这一点。有人试图帮助其他人与类似的问题,但解决方案不适合我。

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


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

这是一个抽屉屏幕的简单例子

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>
}
}

我希望你能帮助我。这是一个重要的导航部分和解决方案将是伟大的!

172013 次浏览

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. Can you please try replacing Home with Stack inside your DrawerNavigator.

Hope this will help :)

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.

In version > 2 follow this:

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


this.props.navigation.dispatch(resetAction);

To use Back, you need to find the unique key associated with the path. 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 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 );

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.

That wipes the stack while navigating from a child navigator to a parent navigator.

Do that if you get this error:

enter image description here

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>.

The Answer is createSwitchNavigator, it those not stack up your navigation. Add your auth screen/navigator in a createSwitchNavigator with the home screen/stack.

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

For newest versions of react-navigation you should use StackActions for reset the stack, here's a piece of code:

// 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...' },
}),
],
}))
}

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 - number - The number of screens to pop back by.

import { StackActions } from 'react-navigation';

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

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. Without using StackActions, it was throwing some error

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

In React Navigation Versions 5.x

You can use StackActions.replace in this version

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>
);
}


React Navigation 5.x , 6.x

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


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

Available in Snack

NavigationActions.reset() seems to be the preferable solution. 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.

SomeComponentScreen.navigationOptions = {
header: null
};

A workaround for this annoyance that worked for me is to consecutively call multiple navigate statements.

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

I found this way to go while using @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.navigation.reset({
index: 0,
routes: [{ name: 'Dashboard' }]
})

React Navigation 6.x

You can use popToTop() action to reset your stack. example:

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


navigation.dispatch(StackActions.popToTop());

React-Navigation Docs: https://reactnavigation.org/docs/stack-actions/#poptotop

This fixed the issue for me (React Navigation 5.x)

import {NavigationActions} from 'react-navigation';


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