React Native

时间:2017-05-27 20:30:48

标签: javascript firebase react-native firebase-authentication

我正在按照教程为我的本机应用程序制作基本的注册/登录功能,但遇到了几个问题。我的代码如下:

App.js

import React, { Component } from 'react';
'use strict';
import {
  AppRegistry,
  Text,
  StyleSheet,
  ActivityIndicator,
  View,
} from 'react-native';
import Navigator from 'react-native-deprecated-custom-components';
import Login from './Login';
import Account from './Account';

import * as firebase from 'firebase';

var firebaseConfig = {
  apiKey: "MY KEY",
  authDomain: "MY DOMAIN",
  databaseURL: "MY URL",
  storageBucket: "MY BUCKET",
};


const firebaseApp = firebase.initializeApp(firebaseConfig);


import styles from '../styles/mainstyle.js';

export default class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      // the page is the screen we want to show the user, we will determine that
      // based on what user the firebase apI returns to us.
      page: null
    };
  }

  componentWillMount(){
    // We must asynchronously get the auth state, if we use currentUser here, it'll be null
    const unsubscribe = firebaseApp.auth().onAuthStateChanged((user) => {
      // If the user is logged in take them to the accounts screen
      if (user != null) {
        this.setState({page: Account});
        return;
      }
      // otherwise have them login
      this.setState({page: Login});
      // unsubscribe this observer
      unsubscribe();
    });


  }



  render() {
    if (this.state.page) {
      return (
        // Take the user to whatever page we set the state to.
        // We will use a transition where the new page will slide in from the right.
        <Navigator
          initialRoute={{component: this.state.page}}
          configureScene={() => {
            return Navigator.SceneConfigs.FloatFromRight;
          }}
          renderScene={(route, navigator) => {
            if(route.component){
              // Pass the navigator the the page so it can navigate as well.
              // Pass firebaseApp so it can make calls to firebase.
              return React.createElement(route.component, { navigator, firebaseApp});
            }
        }} />
      );
    } else {
      return (
        // Our default loading view while waiting to hear back from firebase
        <View style={styles.container}>
          <View style={styles.body}>
            <ActivityIndicator size="large" />
          </View>
        </View>
      );
    }
  }
}

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

Login.js

'use strict';
import {
  AppRegistry,
  Text,
  TextInput,
  View,
  TouchableHighlight,
  ToolbarAndroid,
  ActivityIndicator
} from 'react-native';
import React, {Component} from 'react';
import Signup from './Signup';
import Account from './Account';
import styles from '../styles/mainstyle.js';
import Navigator from 'react-native-deprecated-custom-components';

export default class Login extends Component {

  constructor(props){
    super(props);
    // We have the same props as in our signup.js file and they serve the same purposes.
    this.state = {
      loading: false,
      email: '',
      password: ''
    }
  }

  render() {
    // The content of the screen should be inputs for a username, password and submit button.
    // If we are loading then we display an ActivityIndicator.
    const content = this.state.loading ? <ActivityIndicator size="large"/> :
      <View>
        <TextInput
          style={styles.textInput}
          onChangeText={(text) => this.setState({email: text})}
          value={this.state.email}
          placeholder={"Email Address"} />
        <TextInput
          style={styles.textInput}
          onChangeText={(text) => this.setState({password: text})}
          value={this.state.password}
          secureTextEntry={true}
          placeholder={"Password"} />
        <TouchableHighlight onPress={this.login.bind(this)} style={styles.primaryButton}>
          <Text style={styles.primaryButtonText}>Login</Text>
        </TouchableHighlight>
        <TouchableHighlight onPress={this.goToSignup.bind(this)} style={styles.transparentButton}>
          <Text style={styles.transparentButtonText}>New here?</Text>
        </TouchableHighlight>
      </View>;

    // A simple UI with a toolbar, and content below it.
    return (
        <View style={styles.container}>
        <View style={styles.body}>
          {content}
        </View>
      </View>
        );
  }

  login(){
    this.setState({
      loading: true
    });
    // Log in and display an alert to tell the user what happened.
    this.props.firebaseApp.auth().signInWithEmailAndPassword(this.state.email, this.state.password
    ).then((userData) =>
      {
        this.setState({
            loading: false,
          username:"Joe"
          });
        this.props.navigator.push({
          component: Account
        });
      }
    ).catch((error) =>
        {
          this.setState({
            loading: false
          });
        alert('Login Failed. Please try again' + error.message);
    });
  }

  // Go to the signup page
  goToSignup(){
    this.props.navigator.push({
      component: Signup
    });
  }
}

AppRegistry.registerComponent('Login', () => Login);

Account.js

'use strict';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Image,
  TouchableHighlight,
  ToolbarAndroid
} from 'react-native';
import React, {Component} from 'react';
import Login from './Login';
import styles from '../styles/mainstyle.js';
import Navigator from 'react-native-deprecated-custom-components';
// Styles specific to the account page
const accountStyles = StyleSheet.create({
  email_container: {
    padding: 20
  },
  email_text: {
    fontSize: 18
  }
});

export default class Account extends Component {

  constructor(props) {
    super(props);
    this.state = {
      loading: true,
    }
  }

  componentWillMount() {
    // get the current user from firebase
    const userData = this.props.firebaseApp.auth().currentUser;
    this.setState({
      user: userData,
      loading: false
    });

    console.log(userData);

    console.log(this.props.firebaseApp)

     console.log(this.props.firebaseApp.auth())

      var isNewUser = true;

      var ref = this.props.firebaseApp;
      ref.onAuthStateChanged(function(authData) {
        if (authData && isNewUser) {
          // save the user's profile into the database so we can list users,
          // use them in Security and Firebase Rules, and show profiles
          ref.child("users").child(authData.uid).set({
            provider: authData.provider,
            name: getName(authData)
          });
        }
      });
      // find a suitable name based on the meta info given by each provider
      function getName(authData) {
        switch(authData.provider) {
           case 'password':
             return authData.password.email.replace(/@.*/, '');
           case 'twitter':
             return authData.twitter.displayName;
           case 'facebook':
             return authData.facebook.displayName;
        }
      }



  }

  render() {
    // If we are loading then we display the indicator, if the account is null and we are not loading
    // Then we display nothing. If the account is not null then we display the account info.
    const content = this.state.loading ? <ActivityIndicator size="large"/> :
       this.state.user &&
        <View style={styles.body}>
          <View style={accountStyles.email_container}>
            <Text style={accountStyles.email_text}>{this.state.user.email}</Text>
          </View>
          <TouchableHighlight onPress={this.logout.bind(this)} style={styles.primaryButton}>
            <Text style={styles.primaryButtonText}>Logout</Text>
          </TouchableHighlight>

          <TouchableHighlight onPress={this.logout.bind(this)} style={styles.primaryButton}>
            <Text style={styles.primaryButtonText}>Logout</Text>
          </TouchableHighlight>
        </View>
      ;
    return (
      <View style={styles.container}>
        <View style={styles.body}>
          {content}
        </View>
      </View>
    );
  }

  logout() {
    // logout, once that is complete, return the user to the login screen.
    this.props.firebaseApp.auth().signOut().then(() => {
      this.props.navigator.push({
        component: Login
      });
    });
  }
}

AppRegistry.registerComponent('Account', () => Account);

Signup.js

    'use strict';
    import {
      AppRegistry,
      View,
      ToolbarAndroid,
      ActivityIndicator
    } from 'react-native';
    import { Header,Title,Container, Content, List, ListItem, InputGroup, Input, Icon, Text, Picker, Button } from 'native-base';

import styles from '../styles/mainstyle.js';
import React, {Component} from 'react';
import Login from './Login';
export default class Signup extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // used to display a progress indicator if waiting for a network response.
      loading: false,
      // entered credentials
      email: '',
      password: ''
    }
  }

  // A method to passs the username and password to firebase and make a new user account
  signup() {
    this.setState({
      // When waiting for the firebase server show the loading indicator.
      loading: true
    });

    // Make a call to firebase to create a new user.
    this.props.firebaseApp.auth().createUserWithEmailAndPassword(
      this.state.email,
      this.state.password).then(() => {
        // then and catch are methods that we call on the Promise returned from
        // createUserWithEmailAndPassword
        alert('Your account was created!');
        this.setState({
          // Clear out the fields when the user logs in and hide the progress indicator.
          email: '',
          password: '',
          loading: false
        });
        this.props.navigator.push({
          component: Login
        });
    }).catch((error) => {
      // Leave the fields filled when an error occurs and hide the progress indicator.
      this.setState({
        loading: false
      });
      alert("Account creation failed: " + error.message );
    });
  }

  render() {
    console.log('hello');
    // The content of the screen should be inputs for a username, password and submit button.
    // If we are loading then we display an ActivityIndicator.
    const content = this.state.loading ? <ActivityIndicator size="large"/> :
           <Content>
                <List>
                 <ListItem>
                     <InputGroup>
                     <Icon name="person" style={{ color: '#0A69FE' }} />
                     <Input
                      onChangeText={(text) => this.setState({email: text})}
                      value={this.state.email}
                      placeholder={"Email Address"} />
                      </InputGroup>
                </ListItem>
                <ListItem>
                    <InputGroup>
                      <Icon name="unlock" style={{ color: '#0A69FE' }} />
                    <Input
                      onChangeText={(text) => this.setState({password: text})}
                      value={this.state.password}
                      secureTextEntry={true}
                      placeholder={"Password"} />
                    </InputGroup>
               </ListItem>
              </List>
              <Button style={styles.primaryButton} onPress={this.signup.bind(this)}>
                Signup
              </Button>
              <Button onPress={this.goToLogin.bind(this)} style={styles.primaryButton}>
                Go to Login
              </Button>
      </Content>
    ;
    // A simple UI with a toolbar, and content below it.
        return (
                  <Container>
                  <Header>
                     <Title>Sign Up</Title>
                  </Header>
                  {content}
                  </Container>
                )
  }
  goToLogin(){
    this.props.navigator.push({
      component: Login
    });
  }
}

AppRegistry.registerComponent('Signup', () => Signup);

我收到以下错误: 错误#1: “警告:View.propTypes已被弃用,将在未来版本的ReactNative中删除。请改用ViewPropTypes。”

我一直在查看我的代码,找不到任何对View.protoTypes的引用。我不确定这个错误是指什么。

错误#2: “警告:React.createElement:type无效 - 期望一个字符串(用于内置组件)或一个类/函数(用于复合组件)但得到:object。

检查App的渲染方法。     在App     在RCTView(由View创建)     在视图中(由AppContainer创建)     在RCTView(由View创建)     在视图中(由AppContainer创建)     在AppContainer中“

我已经在这个网站上找到了一个解决方案,并且看到人们提到类导出可能是错误的,但是查看我自己的代码我觉得我已经正确地完成了这个。

错误#3: “错误:元素类型无效:期望一个字符串(用于内置组件)或一个类/函数(用于复合组件)但得到:object。

检查App的渲染方法。

与上述相同,我是否错误地导出了我的课程?

1 个答案:

答案 0 :(得分:1)

警告#1可能与使用已弃用或旧代码的特定软件包有关(React版本不完全支持)。

我认为问题#2和#3可能与导入Navigator的方式有关,而不是如何导出某些类,请尝试:
import { Navigator } from 'react-native-deprecated-custom-components';