首页 > 解决方案 > Firebase注销功能未重定向到expo react本机应用程序上的登录屏幕

问题描述

我正在开发一个 ExpoReact Native 移动应用程序,我正在努力弄清楚如何在运行 firebase.auth().signOut() 方法后将用户重定向到登录屏幕。我想这是我对嵌套导航器不了解的东西,但我会假设一旦我运行注销方法,我的 AppNavigator.js useEffect 函数将在 firebase.auth().onAuthStateChanged 方法中捕获用户状态的变化,然后重新渲染屏幕成为正确的堆栈导航器。请帮助我了解如何使此重定向正常工作以及为什么我当前的构建无法正常工作。

下面是我的主 App.js 文件、包含嵌套导航器的 AppNavigator.js 文件,以及我在单击按钮时运行注销方法的 ProfileScreen.js 文件。

应用程序.js

import React from 'react'

import MainStackNavigator from './src/navigation/AppNavigator'

export default function App() {
  return <MainStackNavigator />
}

应用导航器.js

import 'react-native-gesture-handler';
import React, { useEffect, useState } from 'react'
import { View, Text } from 'react-native';
import { firebase } from '../firebase/config';
import { NavigationContainer } from '@react-navigation/native'
import { createStackNavigator } from '@react-navigation/stack'
import { createMaterialBottomTabNavigator } from '@react-navigation/material-bottom-tabs';
import { LoginScreen, HomeScreen, RegistrationScreen, ProfileScreen } from '../../screens'
import {decode, encode} from 'base-64'
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
if (!global.btoa) {  global.btoa = encode }
if (!global.atob) { global.atob = decode }

const Stack = createStackNavigator();
const Tab = createMaterialBottomTabNavigator()

function MainTabNavigator() {
    return (
      <Tab.Navigator
        initialRouteName="Home"
        activeColor="#fb5b5a"
        inactiveColor="white"
        barStyle={{ backgroundColor: '#465881' }}
      >
        <Tab.Screen 
            name='Home' 
            component={HomeScreen} 
            options={{
                tabBarLabel: 'Home',
                tabBarIcon: ({ color }) => (
                  <MaterialCommunityIcons name="home" color={color} size={26} />
                ),
              }}
        />
        <Tab.Screen 
            name='Profile' 
            component={ProfileScreen} 
            options={{
                tabBarLabel: 'Profile',
                tabBarIcon: ({ color }) => (
                  <MaterialCommunityIcons name="account" color={color} size={26} />
                ),
              }}
        />
      </Tab.Navigator>
    )
  }

function MainStackNavigator() {

  const [loading, setLoading] = useState(true)
  const [user, setUser] = useState(null)

  useEffect(() => {
    const usersRef = firebase.firestore().collection('users');
    firebase.auth().onAuthStateChanged(user => {
      if (user) {
          console.log('Authenticated user')
          console.log(user)
        usersRef.doc(user.uid).get()
          .then((document) => {
            const userData = document.data()
            setLoading(false)
            setUser(userData)
          })
          .catch((error) => {
            setLoading(false)
          });
      } else {
        console.log('signed out user')
        console.log(user)
        setLoading(false)
      }
    });
  }, []);

  if (loading) {
    return (
      
        <View>
            <Text>Loading</Text>
        </View>
      
    )
  }

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

export default MainStackNavigator;

ProfileScreen.js

import React, { useState } from 'react'
import { View, Text, TouchableOpacity } from 'react-native';
import styles from './styles';
import { firebase } from '../../src/firebase/config'

export default function Profile() {

    const onSignoutPress = () => {
        firebase.auth().signOut()
        .then(console.log('signed out'))
    }

    return (
        <View style={styles.container}>
            <Text style={styles.text}>Profile Tab</Text>
            <TouchableOpacity
                style={styles.button}
                onPress={() => onSignoutPress()}>
                <Text style={styles.buttonTitle}>Sign Out</Text>
            </TouchableOpacity>
        </View>
    )
    
}

标签: firebasereact-nativefirebase-authenticationexpo

解决方案


我也注意到了这个问题,所以我将用户而不是置于上下文中的状态(因此它可以在组件之间共享)并且我检查了 userLogged 状态而不是“用户”的登录状态

const [userLogged, setUserLogged] = useState(false);

并在 useEffect 部分中,将其设置为

const authListener = Firebase.auth().onAuthStateChanged((user) => {
 setUserLogged(user ? true : false);

然后你可以使用它 { userLogged == false ?

代替

{ user ?

也让 useEffect 返回 authListener


推荐阅读