Stack navigator giving me undefined error

2020-05-06 11:28发布

问题:

I'm using https://facebook.github.io/react-native/docs/navigation.html by the way.

I'm trying to use the StackNavigator to go from Login.js to AboutDendro.js. What's wrong in my <Button/> component that's throwing that error in my iOS simulator?

Here's Login.js:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ScrollView, Text, TextInput, View, Button, StyleSheet } from 'react-native';
import { login } from '../redux/actions/auth';
import {AuthenticationDetails, CognitoUser, CognitoUserAttribute, CognitoUserPool} from '../lib/aws-cognito-identity';
import StackNavigator from 'react-navigation';
import AboutDendro from './AboutDendro';

const awsCognitoSettings = {
    UserPoolId: 'something',
    ClientId: 'something'
};

class Login extends Component {
    constructor (props) {
        super(props);
        this.state = {
            page: 'Login',
            username: '',
            password: ''
        };
    }

    get alt () { return (this.state.page === 'Login') ? 'SignUp' : 'Login'; }

    handleClick (e) {
        e.preventDefault();
        const userPool = new CognitoUserPool(awsCognitoSettings);

        // Sign up
        if (this.state.page === 'SignUp') {
            const attributeList = [
                new CognitoUserAttribute({ Name: 'email', Value: this.state.username })
            ];
            userPool.signUp(
                this.state.username,
                this.state.password,
                attributeList,
                null,
                (err, result) => {
                    if (err) {
                        alert(err);
                        this.setState({ username: '', password: '' });
                        return;
                    }
                    console.log(`result = ${JSON.stringify(result)}`);
                    this.props.onLogin(this.state.username, this.state.password);
                }
            );
        } else {
            const authDetails = new AuthenticationDetails({
                Username: this.state.username,
                Password: this.state.password
            });
            const cognitoUser = new CognitoUser({
                Username: this.state.username,
                Pool: userPool
            });
            cognitoUser.authenticateUser(authDetails, {
                onSuccess: (result) => {
                    console.log(`access token = ${result.getAccessToken().getJwtToken()}`);
                    this.props.onLogin(this.state.username, this.state.password);
                },
                onFailure: (err) => {
                    alert(err);
                    this.setState({ username: '', password: '' });
                    return;
                }
            });
        }
    }

    togglePage (e) {
        this.setState({ page: this.alt });
        e.preventDefault();
    }

    static navigationOptions = {
        title: 'AboutDendro',
    };

    render() {
        const { navigate } = this.props.navigation;
        const App = StackNavigator({
            Home: { screen: Login },
            Profile: { screen: AboutDendro },
        });

        return (
            <ScrollView style={{padding: 20}}>
                <Button
                    title="Go to Jane's profile"
                    onPress={() =>
                        navigate('AboutDendro', { name: 'AboutDendro' })
                    }
                />
                <Text style={{fontSize: 27}}>{this.state.page}</Text>
                <TextInput
                    placeholder='Email Address'
                    autoCapitalize='none'
                    autoCorrect={false}
                    autoFocus={true}
                    keyboardType='email-address'
                    value={this.state.username}
                    onChangeText={(text) => this.setState({ username: text })} />
                <TextInput
                    placeholder='Password'
                    autoCapitalize='none'
                    autoCorrect={false}
                    secureTextEntry={true}
                    value={this.state.password}
                    onChangeText={(text) => this.setState({ password: text })} />
                <View style={{margin: 7}}/>
                <Button onPress={(e) => this.handleClick(e)} title={this.state.page}/>
                <View style={styles.firstView}>
                    <Text onPress={(e) => this.togglePage(e)} style={styles.buttons}>
                        {this.alt}
                    </Text>
                </View>
            </ScrollView>
        );
    }
}

const styles = StyleSheet.create({
    buttons: {
        fontSize: 12,
        color: 'blue',
        flex: 1
    },

    firstView: {
        margin: 7,
        flexDirection: 'row',
        justifyContent: 'center'
    }
});

const mapStateToProps = (state, ownProps) => {
    return {
        isLoggedIn: state.auth.isLoggedIn
    };
}

const mapDispatchToProps = (dispatch) => {
    return {
        onLogin: (username, password) => { dispatch(login(username, password)); }
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Login);

回答1:

It is because navigation is not in your props. It is a part of your App component you created. But you do nothing with this component.

You should have an App.js file, with your stackNavigator, set your Login component as your default component in your stackNavigator's parameters.

Take a look at this documentation



回答2:

I try to refactor your code. in component render maybe you can just write :

render() {
    const { navigate } = this.props.navigation;
    return (
        <ScrollView style={{padding: 20}}>
            <Button
                title="Go to Jane's profile"
                onPress={() =>
                    navigate('Profile', { name: 'AboutDendro' })
                }
            />
            <Text style={{fontSize: 27}}>{this.state.page}</Text>
            <TextInput
                placeholder='Email Address'
                autoCapitalize='none'
                autoCorrect={false}
                autoFocus={true}
                keyboardType='email-address'
                value={this.state.username}
                onChangeText={(text) => this.setState({ username: text })} />
            <TextInput
                placeholder='Password'
                autoCapitalize='none'
                autoCorrect={false}
                secureTextEntry={true}
                value={this.state.password}
                onChangeText={(text) => this.setState({ password: text })} />
            <View style={{margin: 7}}/>
            <Button onPress={(e) => this.handleClick(e)} title={this.state.page}/>
            <View style={styles.firstView}>
                <Text onPress={(e) => this.togglePage(e)} style={styles.buttons}>
                    {this.alt}
                </Text>
            </View>
        </ScrollView>
    );
  }
}

And you separate component StackNavigation below component render() like:

 const App = StackNavigator({
        Home: { screen: Login },
        Profile: { screen: AboutDendro },
    });

And then import component App in your index.ios.js like:

import './Login';

just that. Maybe my answer can help you.