我正在按照教程为我的本机应用程序制作基本的注册/登录功能,但遇到了几个问题。我的代码如下:
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
的渲染方法。
与上述相同,我是否错误地导出了我的课程?
答案 0 :(得分:1)
警告#1可能与使用已弃用或旧代码的特定软件包有关(React版本不完全支持)。
我认为问题#2和#3可能与导入Navigator的方式有关,而不是如何导出某些类,请尝试:
import { Navigator } from 'react-native-deprecated-custom-components';