Problem switching / navigating from LoginScreen to HomeScreen using Firebase Authentication in React Native App

huangapple go评论137阅读模式
英文:

Problem switching / navigating from LoginScreen to HomeScreen using Firebase Authentication in React Native App

问题

我正在尝试构建一个React Native应用程序。作为数据库,我正在使用Firebase,用于用户管理,我正在使用Firebase身份验证(https://firebase.google.com/docs/auth?hl=en)。
我有一个(看起来)非常简单的问题。我可以使用Firebase函数createUserWithEmailAndPassword在应用程序中创建新用户,并且也可以使用Firebase函数signInWithEmailAndPassword进行登录,但在登录后,用户没有被定向或导航到HomeScreen页面。<br>
因此,目前我的应用程序只包括两个屏幕,登录和主屏幕。以下是两个屏幕以及App.js和package.json文件的代码。

一段时间前,Firebase身份验证确实起作用,我手动使用reactnavigation(https://reactnavigation.org/)在主屏幕和登录屏幕之间导航用户。但自从我不得不升级Firebase到版本10以来,似乎不再起作用。
在构建这个基本应用程序时,我遵循了这个教程:https://www.youtube.com/watch?v=ONAVmsGW6-M&t=1164s。在那里,开发者使用TypeScript,但根据我的看法,对我来说应该是一样的方式。
我认为可能有问题的代码行可能是

{user ? &lt;Stack.Screen name=&quot;Login&quot; component={Login} options={{ headerShown: false}} /&gt; : &lt;Stack.Screen name=&quot;Home&quot; component={HomeScreen} options={{ headerShown: false}} /&gt;}

因为在那里要显示的屏幕是根据我的用户状态确定的。我检查过在调用setUser(user);后,用户对象在状态中被正确设置。我不明白为什么YouTube教程中使用的代码似乎对我不起作用,以及为什么我无法让这个基本的Firebase身份验证起作用。我非常感谢任何提示和想法,并将乐意提供更多信息(如果需要的话)。在这上面花了一些时间,所以提前感谢任何帮助!

App.js

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import Login from './screens/LoginScreen';
import HomeScreen from './screens/HomeScreen';
import { useEffect, useState } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import { FIREBASE_AUTH } from './config';

const Stack = createNativeStackNavigator();

export default function App() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    onAuthStateChanged(FIREBASE_AUTH, (user) => {
      console.log('user: ', user);
      setUser(user);
    })
  })

  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName='Login'>
        {user ? <Stack.Screen name="Login" component={Login} options={{ headerShown: false}} /> : <Stack.Screen name="Home" component={HomeScreen} options={{ headerShown: false}} />}
      </Stack.Navigator>
    </NavigationContainer>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

LoginScreen.js

import {View, Text, StyleSheet} from 'react-native';
import React, { useState } from 'react';
import { FIREBASE_AUTH } from '../config';
import { SafeAreaView } from 'react-native-safe-area-context';
import { TextInput } from 'react-native';
import { createUserWithEmailAndPassword, signInWithEmailAndPassword } from 'firebase/auth';
import { Button } from 'react-native';

const Login = () => {
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const auth = FIREBASE_AUTH;

    const signIn = async() => {
        try {
            const response = await signInWithEmailAndPassword(auth, email, password);
            console.log(response);
        } catch (error) {
            console.log(error);
            alert('Sign in failed: ' + error.message);
        } 
    }

    const signUp = async() => {
        try {
            const response = await createUserWithEmailAndPassword(auth, email, password);
            console.log(response);
            alert('Check your emails!');
        } catch (error) {
            console.log(error);
            alert('Registration failed: ' + error.message);
        } 
    }

    return (
        <SafeAreaView style={styles.container}>
            <TextInput value={email} style={styles.input} placeholder='Email' autoCapitalize='none' onChangeText={(text) => setEmail(text)}></TextInput>
            <TextInput secureTextEntry={true} value={password} style={styles.input} placeholder='Password' autoCapitalize='none' onChangeText={(text) => setPassword(text)}></TextInput>

            <Button title='Login' onPress={signIn} />
            <Button title="Create account" onPress={signUp} />
        </SafeAreaView>
    );
};

export default Login;

const styles = StyleSheet.create({
    container: {
        marginHorizontal: 20, 
        flex: 1, 
        justifyContent: 'center'
    }, 
    input: {
        marginVertical: 4,
        height: 50, 
        borderWidth: 1, 
        borderRadius: 4, 
        padding: 10, 
        backgroundColor: '#fff'
    }
})

HomeScreen.js

import { View, Text } from 'react-native';
import React from 'react';

const HomeScreen = () => {
    return (
        <View>
            <Text>List</Text>
        </View>
    )
}

export default HomeScreen;

package.json

{
  "name": "testprojectnavigation",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web"
  },
  "dependencies": {
    "@react-navigation/native": "^6.1.7",
    "@react-navigation/native-stack": "^6.9.13",
    "expo": "~48.0.18",
    "expo-status-bar": "~1.4.4",
    "firebase": "^10.0.0",
    "react": "18.2.0",
    "react-native": "0.71.8",
    "react-native-safe-area-context": "4.5.0",
    "react-native-screens": "~3.20.0"
  },
 

<details>
<summary>英文:</summary>

I am trying to build a React Native App. As database, I&#39;m using Firebase and for User Management, I&#39;m using Firebase Authentication (https://firebase.google.com/docs/auth?hl=en).
I have a (seemingly) very simple problem. I can create new Users in the app with the firebase function ```createUserWithEmailAndPassword``` and login too using the firebase function ```signInWithEmailAndPassword```, but after the login, the user is not directed or navigated to the HomeScreen. &lt;br&gt;
So currently my app only consists of two screens, the login and the home screen. The code for both screens and the App.js as well as the package.json file is provided below.
Some time ago, the firebase authentication did work and I manually navigated users using reactnavigation (https://reactnavigation.org/) between home- and login-screen. But since I had to upgrade firebase to version 10, it seems to not work that way anymore. 
While building this basic app, I followed this tutorial: https://www.youtube.com/watch?v=ONAVmsGW6-M&amp;t=1164s . There, the developer is using TypeScript, but it should work the same way for me according to my opinion. 
I think the problematic line of code might be 

{user ? <Stack.Screen name="Login" component={Login} options={{ headerShown: false}} /> : <Stack.Screen name="Home" component={HomeScreen} options={{ headerShown: false}} />}

since there the screen to be displayed is determined in dependance of my user state. I checked that after the call so setUser(user);, the user object is correctly set in the state. I don&#39;t understand why the code used in the youtube tutorial does not seem to work for me and why I couldn&#39;t get this basic firebase authentication to work. I am very thankful for any tips and ideas and will happily provide more information if needed. Spent some time on this, so thanks in advance for any help!
App.js

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import Login from './screens/LoginScreen';
import HomeScreen from './screens/HomeScreen';
import { useEffect, useState } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import { FIREBASE_AUTH } from './config';

const Stack = createNativeStackNavigator();

export default function App() {
const [user, setUser] = useState(null);

useEffect(() => {
onAuthStateChanged(FIREBASE_AUTH, (user) => {
console.log('user: ', user);
setUser(user);
})
})

return (
<NavigationContainer>
<Stack.Navigator initialRouteName='Login'>
{user ? <Stack.Screen name="Login" component={Login} options={{ headerShown: false}} /> : <Stack.Screen name="Home" component={HomeScreen} options={{ headerShown: false}} />}
</Stack.Navigator>
</NavigationContainer>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});


LoginScreen.js

import {View, Text, StyleSheet} from 'react-native';
import React, { useState } from 'react';
import { FIREBASE_AUTH } from '../config';
import { SafeAreaView } from 'react-native-safe-area-context';
import { TextInput } from 'react-native';
import { createUserWithEmailAndPassword, signInWithEmailAndPassword } from 'firebase/auth';
import { Button } from 'react-native';

const Login = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const auth = FIREBASE_AUTH;

const signIn = async() =&gt; {
try {
const response = await signInWithEmailAndPassword(auth, email, password);
console.log(response);
} catch (error) {
console.log(error);
alert(&#39;Sign in failed: &#39; + error.message);
} 
}
const signUp = async() =&gt; {
try {
const response = await createUserWithEmailAndPassword(auth, email, password);
console.log(response);
alert(&#39;Check your emails!&#39;);
} catch (error) {
console.log(error);
alert(&#39;Registration failed: &#39; + error.message);
} 
}
return (
&lt;SafeAreaView style={styles.container}&gt;
&lt;TextInput value={email} style={styles.input} placeholder=&#39;Email&#39; autoCapitalize=&#39;none&#39; onChangeText={(text) =&gt; setEmail(text)}&gt;&lt;/TextInput&gt;
&lt;TextInput secureTextEntry={true} value={password} style={styles.input} placeholder=&#39;Password&#39; autoCapitalize=&#39;none&#39; onChangeText={(text) =&gt; setPassword(text)}&gt;&lt;/TextInput&gt;
&lt;Button title=&#39;Login&#39; onPress={signIn} /&gt;
&lt;Button title=&quot;Create account&quot; onPress={signUp} /&gt;
&lt;/SafeAreaView&gt;
);

};

export default Login;

const styles = StyleSheet.create({
container: {
marginHorizontal: 20,
flex: 1,
justifyContent: 'center'
},
input: {
marginVertical: 4,
height: 50,
borderWidth: 1,
borderRadius: 4,
padding: 10,
backgroundColor: '#fff'
}
})

HomeScreen.js

import { View, Text } from 'react-native';
import { React } from 'react';

const HomeScreen = () => {
return (
<View>
<Text>List</Text>
</View>
)
}

export default HomeScreen;


package.json

{
"name": "testprojectnavigation",
"version": "1.0.0",
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web"
},
"dependencies": {
"@react-navigation/native": "^6.1.7",
"@react-navigation/native-stack": "^6.9.13",
"expo": "~48.0.18",
"expo-status-bar": "~1.4.4",
"firebase": "^10.0.0",
"react": "18.2.0",
"react-native": "0.71.8",
"react-native-safe-area-context": "4.5.0",
"react-native-screens": "~3.20.0"
},
"devDependencies": {
"@babel/core": "^7.20.0"
},
"private": true
}


I am using react-native-cli: 2.0.1
</details>
# 答案1
**得分**: 2
如果用户已定义,则转到登录页面,否则转到主页。你不希望反过来吗?
<details>
<summary>英文:</summary>
In your
```typescript
{user ? &lt;Stack.Screen name=&quot;Login&quot; component={Login} options={{ headerShown: false}} /&gt; : &lt;Stack.Screen name=&quot;Home&quot; component={HomeScreen} options={{ headerShown: false}} /&gt;}

If user is defined, go to Login, otherwise go to Home.
Don't you want this to be the other way around?

huangapple
  • 本文由 发表于 2023年7月23日 20:35:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76748266.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定