首页 > 解决方案 > 使用带有切换屏幕的 StackNavigator 时出错

问题描述

我正在尝试使用 stackNavigator 制作注册/登录屏幕。但是当我尝试从登录页面导航到注册页面时。

我尝试创建一个 const 作为导航属性,但我得到了相同的结果。如果我使用 stackNavigator 在同一个文件中完成所有屏幕,我不会收到错误消息,但这并不是我真正想要做的。

这是我的登录屏幕首先(在进入 index.js 中的这个屏幕之前,我调用 Welcome 类来检查用户是否登录,如果他没有登录,我会返回

export default class Login extends React.Component{
    render(){

        return( 
          <ScrollView style={{padding : 20}}>
            <Text style={styles.title}>
              Login
            </Text>
            <TextInput style={styles.input} placeholder="Email Address"/>
            <TextInput style={styles.input} placeholder="Password" />
            <View style={{margin : 7}}/>
            <TouchableOpacity
            onPress={() => this.props.navigation.navigate('Signup')}
            >
              <Text> Don't have an account? Click here</Text>
            </TouchableOpacity>
            <Button
              onPress={this.props.onLoginPress}
              title="Log in"
              color='grey'
              />
          </ScrollView>   
        );
    }
}

我的注册屏幕很空,它现在只返回一个带有标题的视图最后这是我的 StackNavigator 文件

const AppNavigator = createStackNavigator({
  Welcome: {
      screen : Welcome
  } , 
  Login: {
    screen: Login
  },
  Signup : {
      screen : Signup
  },

},
{
    initialRouteName: "Welcome"
});

export default createAppContainer(AppNavigator);

Welcome 是检查用户是否登录的文件不是

我得到的错误是“错误未定义不是一个对象(评估'_this.props.navigation.navigate')。” 当我单击 Login.js 中的

标签: androidreact-nativereact-navigation

解决方案


检查你的回购。你的welcome屏幕首先检查用户是否登录,如果没有登录,它会渲染屏幕login。您不是在屏幕之间导航,而是呈现另一个登录屏幕。问题就在这里。我举个例子:WelcomeLogin

在您的手机(例如 iPhone X)中,您从 App Store 下载并安装了 Facebook。然后您登录了您的帐户。这意味着,您手机中的 Facebook 应用程序现在已配置为使用您的帐户。现在,如果您想发布您的照片,如果您下载并安装另一个 Facebook 应用程序并尝试从那里发布,您将无法做到这一点。您将必须使用配置为使用您的帐户的同一旧应用程序。(实际上您将无法一次下载两个:P)

同样,您应该告诉堆栈导航器导航到堆栈导航器的login屏幕,而不是渲染另一个login屏幕。您创建的新login屏幕将没有导航道具,除非您通过一个。

但还有另一种方式。您可以像渲染signup屏幕一样渲染login屏幕。将此代码复制到您的Welcome.js

import React from 'react';
import { Text, View, Button } from 'react-native';
import LoginScreen from './LoginScreen';
import SignupScreen from './Signup';
import DrawerNavigator from '../navigation/DrawerNavigator';

const notLoggedIn=0, loggedIn=1, signingUp=2;

export default class Welcome extends React.Component{
    constructor(props){
        super(props);
        this.state={
            state: notLoggedIn
        }
    }

    render(){
        switch (this.state.state){
            case notLoggedIn:
                return (
                    <LoginScreen
                        onLoginPress={()=>this.setState({state:loggedIn})}
                        onSignUpPress={()=>this.setState({state:signingUp})}
                    />
                );
            case loggedIn:
                return <DrawerNavigator />;
            case signingUp:
                return <SignupScreen />; //Add onBackPress={()=>this.setState({state:notLoggedIn})}} prop here if you want
        }
    }
}

然后在你的Login.js,将 onPress 道具从 更改this.props.navigation.navigate('Signup')this.props.onSignUpPress()

您现在不需要堆栈导航器。(您现在拥有自己的导航器)因此,您现在可以直接使用您的Welcome屏幕,而不是使用该堆栈导航器。现在您可以删除 stacknavigator.js 文件。

我想这应该可以解决。

提示:看到您的文件中有许多未使用的样式和导入。如果你真的不打算使用它们,你可以删除这些行。这取决于你。

编辑:

要将函数传递给导航器,您可以使用 screenProps 道具。

编辑您的Welcome.js

case loggedIn:
  return <DrawerNavigator logout={()=>this.setState({state:notLoggedIn})} />;

DrawerNavigator.js

...
const DrawerNavigator = createAppContainer(createDrawerNavigator(
  ...
));

export default class navigator extends React.Component {
  render(){
    return <DrawerNavigator screenProps={{logout: this.props.logout}} />
  }
}

在你的内部logout.js,从你想要的任何地方调用函数this.props.screenProps.logout()。这应该有效。


推荐阅读