簡體   English   中英

從嵌套堆棧導航器導航到根屏幕

[英]Navigate to root screen from nested stack navigator

我是新來的,並試圖自己學習,我在將用戶從嵌套的 stck 導航器屏幕導航回根屏幕時遇到了問題。

這是我的一些課程:-

index.android.js :-

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  StatusBar,
  View
} from 'react-native';
import {LoginStack} from './login/loginregisterrouter';
import {StackNavigator } from 'react-navigation';
class reactNavigationSample extends Component {
  render(){
    return (
   <LoginStack/>
    );
  }
}
AppRegistry.registerComponent('MssReactDemo', () => reactNavigationSample);

登錄注冊路由器:-

import React from 'react';
import {StackNavigator } from 'react-navigation';
import LoginScreen from './LoginScreen';
import RegisterScreen from './RegisterScreen';
import NavigationContainer from './navigationContainer';
export const LoginStack = StackNavigator({
  LoginScreen: {
    screen: LoginScreen,
    navigationOptions: {
      title: 'LoginScreen',
    }
  },
  RegisterScreen: {
    screen: RegisterScreen,
    navigationOptions: ({ navigation }) => ({
      title: 'RegisterScreen',
    }),
  },NavigationContainer: {
        screen: NavigationContainer,
        navigationOptions: ({ navigation }) => ({
          title: 'NavigationContainer', header: null,
        }),
      },
});

導航容器.js :-

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  StatusBar,
  View
} from 'react-native';
import {EasyRNRoute,} from '../parent';
import {StackNavigator } from 'react-navigation';
export default class NavigationContainer extends Component {
  render(){
    return (
   <EasyRNRoute/>
    );
  }
}

parent.js :-

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  StatusBar,
  View
} from 'react-native';
import App from './app';
import DrawerMenu from './Drawer/drawer-toolbar-android';
import BookmarkView from './Pages/bookmark';
import ClientView from './Pages/client';
import InfoView from './Pages/info';
import SettingsView from './Pages/setting';
import { DrawerNavigator, StackNavigator } from 'react-navigation';

export const stackNavigator = StackNavigator({
  Info: { screen: InfoView },
  Settings: {screen: SettingsView },
  Bookmark: {screen: BookmarkView },
  Connections: {screen: ClientView},
}, {
  headerMode: 'none'
});

export const EasyRNRoute = DrawerNavigator({
  Home: {
    screen: App,
  },
  Stack: {
    screen: stackNavigator
  }
}, {
  contentComponent: DrawerMenu,
  contentOptions: {
    activeTintColor: '#e91e63',
    style: {
      flex: 1,
      paddingTop: 15,
    }
  }
});

抽屜工具欄-android.js :-

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    StatusBar,
    View
} from 'react-native';
import { NavigationActions } from 'react-navigation'
import { COLOR, ThemeProvider, Toolbar, Drawer, Avatar } from 'react-native-material-ui';
import Container from '../Container';
import LoginScreen from '../login/LoginScreen';

const uiTheme = {
    palette: {
        primaryColor: COLOR.green500,
        accentColor: COLOR.pink500,
      },
    toolbar: {
        container: {
            height: 70,
            paddingTop: 20,
          },
      },
      avatar: {
          container: {
              backgroundColor: '#333'
          }
      }
  };

export default class DrawerMenu extends Component {
  constructor(props, context) {
    super(props, context);
    this.state = {
        active: 'people',
      };
  }
handleLogoutPress = () => {
//    AsyncStorage.setItem('SignedUpuser', '');
this.props
               .navigation
               .dispatch(NavigationActions.reset(
                 {
                    index: 0,
                    actions: [
                      NavigationActions.navigate({ routeName: 'LoginScreen'})
                    ]
                  }));
//     this.props.navigation.dispatch(NavigationActions.back());
  };
  _setInfoActive() {
    this.setState({ active: 'info' });
  }

  render() {
    return (
        <ThemeProvider uiTheme={uiTheme}>
                <Container>
                    <StatusBar backgroundColor="rgba(0, 0, 0, 0.2)" translucent />
                    <Toolbar
                    leftElement="arrow-back"
                    onLeftElementPress={() => this.props.navigation.navigate('DrawerClose')}
                    centerElement="Menu"
                />
                    <View style={styles.container}>
                        <Drawer>
                            <Drawer.Header >
                                <Drawer.Header.Account
                                style={{ 
                                    container: { backgroundColor: '#fafafa' },
                                }}
                                avatar={<Avatar text={'S'} />}
//                                accounts={[
//                                    { avatar: <Avatar text="H" /> },
//                                    { avatar: <Avatar text="L" /> },
//                                ]}
                                footer={{
                                    dense: true,
                                    centerElement: {
                                        primaryText: 'Siddharth',
                                        secondaryText: 'I am DONE now',
                                    },

                                  }}
                            />
                            </Drawer.Header>
                            <Drawer.Section
                            style={{
                                label: {color: '#0000ff'}
                            }}
                            divider
                            items={[
                                {
                                    icon: 'bookmark-border', value: 'Bookmarks',
                                    active: this.state.active == 'bookmark',
                                    onPress: () => {
                                        this.setState({ active: 'bookmark' });
                                        this.props.navigation.navigate('Bookmark');
                                      },
                                  },
                                {
                                    icon: 'people', value: 'Connections',
                                    active: this.state.active == 'Connection',
                                    onPress: () => {
                                        this.setState({ active: 'Connection' });
                                        this.props.navigation.navigate('Connections');
                                      },
                                  },
                            ]}
                        />
                            <Drawer.Section
                            title="Personal"
                            items={[
                                {
                                    icon: 'info', value: 'Info',
                                    active: this.state.active == 'info',
                                    onPress: () => {
                                        this.setState({ active: 'info' });
                                        //this.props.navigation.navigate('DrawerClose');
                                        this.props.navigation.navigate('Info');
                                      },
                                  },
                                {
                                    icon: 'settings', value: 'Settings',
                                    active: this.state.active == 'settings',
                                    onPress: () => {
                                        this.setState({ active: 'settings' });
                                        this.props.navigation.navigate('Settings');
                                      },
                                  },
                                   {
                                    icon: 'logout', value: 'Logout',
                                    active: this.state.active == 'logout',
                                    onPress: () => {
                                    this.handleLogoutPress();
                                     },
                                      },
                            ]}
                        />
                        </Drawer>
                    </View>
                </Container>
            </ThemeProvider>
    );
  }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#F5FCFF',
      },
    header: {
        backgroundColor: '#455A64',
      },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
      },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
      },
  });

以上是我在我的應用程序中使用的堆棧體系結構,正如您所看到的,我的主屏幕是登錄屏幕,我確實可以選擇從我的抽屜(側面菜單)中的應用程序注銷。 我真正想要的是,當用戶點擊注銷時,他/她應該被重定向到登錄屏幕。 我已經用谷歌搜索了這個並了解了兩種方法,但這兩種方法都不適合我,可能是我以錯誤的方式使用它們。 所以我在這里尋求你的幫助。

這兩種方法是:-

1)

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

2) this.props.navigation.dispatch(NavigationActions.back());

這個問題對你來說可能看起來很愚蠢,但我真的被困在這一點上,只是想知道我該如何解決這個問題。任何幫助將不勝感激!!!! 提前致謝。

在嘗試了幾乎所有事情之后,我找到了對我有用的解決方案:

  this.props.navigation.popToTop(); // go to the top of the stack
  this.props.navigation.goBack(null); // now show the root screen

包含 Dismissable StackNavigator 的模態 StackNavigator

要求: react-navigation版本: 1.0.0

目標:App TabNavigator 導航到Screen 1Screen 2Screen N ,然后直接返回App TabNavigator。

導航層級:

  • RootNavigator StackNavigator {mode: 'modal'}
    • 應用程序TabNavigator
      • 選項卡Screen
      • 選項卡Screen
      • 選項卡Screen
    • 模態Screen
    • ModalStack DismissableStackNavigator
      • 屏幕 1 ModalStackScreen
      • 屏幕 2 ModalStackScreen
      • 屏幕 N ModalStackScreen

演示

可關閉的 StackNavigator

package.json

{
  "name": "HelloWorld",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  },
  "dependencies": {
    "react": "16.0.0-alpha.6",
    "react-native": "0.44.0",
    "react-navigation": "^1.0.0"
  },
  "devDependencies": {
    "babel-jest": "20.0.3",
    "babel-preset-react-native": "1.9.2",
    "jest": "20.0.3",
    "react-test-renderer": "16.0.0-alpha.6"
  },
  "jest": {
    "preset": "react-native"
  }
}

index.ios.js (或index.android.js

import React from 'react'
import {
  AppRegistry,
  Button,
  Text,
  View
} from 'react-native'
import {
  StackNavigator,
  TabNavigator
} from 'react-navigation'

class TabA extends React.Component {
  state = {
    startScreen: 'none',
    returnScreen: 'none'
  }
  render () {
    return (
      <View style={{ padding: 40, paddingTop: 64 }}>
        <Text style={{ fontSize: 20 }}>{this.constructor.name}</Text>
        <Text>startScreen: {this.state.startScreen}</Text>
        <Text>returnScreen: {this.state.returnScreen}</Text>
        <Button
          title="Open ModalScreen"
          onPress={() => this.props.navigation.navigate('ModalScreen', {
            startScreen: this.constructor.name,
            setParentState: (state) => this.setState(state)
          })}
        />
        <Button
          title="Open ModalStack"
          onPress={() => this.props.navigation.navigate('ModalStack', {
            startScreen: this.constructor.name,
            setParentState: (state) => this.setState(state)
          })}
        />
      </View>
    )
  }
}

class TabB extends TabA {}
class TabC extends TabA {}

class ModalScreen extends React.Component {
  render () {
    const {
      startScreen,
      setParentState
    } = this.props.navigation.state.params
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text style={{ fontSize: 20 }}>{this.constructor.name}</Text>
        <Button
          title="Close"
          onPress={() => {
            setParentState({
              startScreen,
              returnScreen: this.constructor.name
            })
            this.props.navigation.goBack()
          }}
        />
      </View>
    )
  }
}


const DismissableStackNavigator = (routes, options) => {
  const StackNav = StackNavigator(routes, options)

  return class DismissableStackNav extends React.Component {
    static router = StackNav.router

    render () {
      const { state, goBack } = this.props.navigation
      const screenProps = {
        ...this.props.screenProps,
        dismissStackNav: () => goBack(state.key)
      }
      return (
        <StackNav
          screenProps={screenProps}
          navigation={this.props.navigation}
        />
      )
    }
  }
}

class ModalStackScreen extends React.Component {
  render () {
    const screenNumber = this.props.navigation.state.params && this.props.navigation.state.params.screenNumber || 0
    const {
      startScreen,
      setParentState
    } = this.props.navigation.state.params
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text style={{ fontSize: 20 }}>{this.constructor.name + screenNumber}</Text>
        <View style={{
          flexDirection: 'row',
          justifyContent: 'space-between'
        }}>
          <Button
            title={screenNumber === 0 ? "Close" : "Back"}
            onPress={() => this.props.navigation.goBack(null)}
          />
          <Button
            title="Save"
            onPress={() => {
              setParentState({
                startScreen,
                returnScreen: this.constructor.name + screenNumber
              })
              this.props.screenProps.dismissStackNav()
            }}
          />
          <Button
            title="Next"
            onPress={() => this.props.navigation.navigate('ModalStackScreen', {
              screenNumber: screenNumber + 1,
              startScreen,
              setParentState
            })}
          />
        </View>
      </View>
    )
  }
}

const TabNav = TabNavigator(
  {
    TabA: {
      screen: TabA
    },
    TabB: {
      screen: TabB
    },
    TabC: {
      screen: TabC
    }
  }
)

const ModalStack = DismissableStackNavigator(
  {
    ModalStackScreen: {
      screen: ModalStackScreen
    }
  },
  {
    headerMode: 'none'
  }
)

const RootStack = StackNavigator(
  {
    Main: {
      screen: TabNav,
    },
    ModalScreen: {
      screen: ModalScreen,
    },
    ModalStack: {
      screen: ModalStack
    }
  },
  {
    mode: 'modal',
    headerMode: 'none'
  }
)

class App extends React.Component {
  render () {
    return <RootStack />
  }
}

AppRegistry.registerComponent('HelloWorld', () => App)

上一個答案

這個解決方案是一個大錘。 它會導致 TabNavigator 中默認選項卡的屏幕卸載然后再次裝載。 如果使用 StackNavigator 啟動 Modal 的 Screen a 選項卡傳遞一些回調以更新其狀態,則將在卸載 Screen 時調用這些回調。

解決方案是將key: null添加到重置對象中:

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

我被這條評論打動了

(僅供參考 - 我是通過您的評論來到這里尋求幫助的。)

根據反應導航文檔,您可以通過以下方式轉到任何堆棧:查看以下鏈接以獲取更多詳細信息React-navigation stack action link

1. import { StackActions, NavigationActions } from 'react-navigation';
         const resetAction = StackActions.reset({
          index: 0,
          actions: [NavigationActions.navigate({ routeName: 'Profile' })],
        });
        this.props.navigation.dispatch(resetAction);
  1. 如果您有一個用於配置文件的堆棧,那么您也可以通過以下鏈接嵌套反應導航進行這樣的檢查

 import { NavigationActions } from 'react-navigation'; const navigateAction = NavigationActions.navigate({ routeName: 'Profile', params: {}, action: NavigationActions.navigate({ routeName: 'SubProfileRoute' }), }); this.props.navigation.dispatch(navigateAction);

(React Navigation 5.x)我遇到了像“ https://reactnavigation.org/docs/en/auth-flow.html ”中的示例那樣有條件地呈現屏幕的問題據我了解,這意味着堆棧導航器不是“渲染”,因此無法找到彼此。 我所做的是以下和注銷頁面:

navigation.replace('SplashScreen')

我的邏輯是:SplashScreen(檢查 AsyncStorage 令牌),

if (token){
navigation.navigate('App')
}else{
navigation.navigate('StartScreen')
}

在 StartScreen 中,只需導航到登錄或注冊,如果登錄成功,您將返回應用程序。

作為參考,

function AppBottomNavigator(){
  return(
    <AppNavigator.Navigator 
      initialRouteName={'Home'} ...}>
        <AppNavigator.Screen name='A' component={ScreenA}/>
        <AppNavigator.Screen name='B' component={ScreenB}/>
        <AppNavigator.Screen name='C' component={ScreenC}/>
        <AppNavigator.Screen name='D' component={ScreenD}/>
        <AppNavigator.Screen name='E' component={ScreenE}/>
    </AppNavigator.Navigator>
  )
}

導出默認應用程序內容...

 ...return(
        <AuthContext.Provider value={authContext}>
          <NavigationContainer>
            <AuthStack.Navigator screenOptions={{headerShown:false}}>
              <>
                <AuthStack.Screen name='SplashScreen' component={SplashScreen}/>
                <AuthStack.Screen name='StartScreen' component={StartScreen} />
                <AuthStack.Screen name='SignIn' component={SignIn} />
                <AuthStack.Screen name='Register' component={Register} />
                <AuthStack.Screen name='App' component={AppBottomNavigator}/>
              </>
            </AuthStack.Navigator>
          </NavigationContainer>
        </AuthContext.Provider>
      )

我對此也很陌生,但它有效,所以如果其他人有更安全/更整潔/通用的解決方案,我也很想知道。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM