You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native项目基于Firebase REST API实现退出登录方案求助

React Native 退出登录功能实现求助

我是React Native新手,项目通过Firebase REST API完成用户认证,需在Profile.js组件中实现logOut函数。当前登录状态由useAuth Hook管理,导航逻辑为:未登录时使用Stack Navigator,登录后切换为Tab Navigator。尝试多种方法均未成功,怀疑是导航结构导致问题,请求帮助实现退出登录功能。

相关代码

Profile.js

const Profile = () => {
  const [user] = useAuth()
  const navigation = useNavigation()
  const logOut = () => {
    // 待实现的退出逻辑
  };

  return (
    <View style={styles.container}>
        <View style={styles.header}>
            <Image
                source={require('../assets/images/Logo_small.png')}
                style={styles.logo_s}
                resizeMode='contain'/>
        </View>
        <View style={styles.main_cont}>
            <Profile_text marginBottom={28}/>
            <View style={styles.replace}>
              <TextInput
                style={styles.inp}
                placeholder={user.displayName}
                placeholderTextColor= 'rgba(207, 77, 79, 0.75)'
                editable={false}/>
              <Pressable onPress={''}>
                <Image
                  source={require('../assets/images/replace_btn.png')}
                  style={styles.replace_btn}
                  resizeMode='contain'/>
              </Pressable>
            </View>
            <UnderLine marginBottom={500}/>
            <Pressable style={styles.result} onPress={logOut}>
                <Text style={styles.text_result}>Выйти из профиля</Text>
            </Pressable>
        </View>
        <Image
        source={require('../assets/images/bottom_menu.png')}
        style={styles.img_bg}/>
    </View>
  )
}

App.js

const Stack = createNativeStackNavigator();

const Navigator = () => {
  const [user] = useAuth()

  if(!user) {
    return (
      <Stack.Navigator
      screenOptions={{
        headerShown: false
      }}>
        <Stack.Screen  name="Login" component={LoginScreen} />
        <Stack.Screen name="Registration" component={RegistrationScreen} />
      </Stack.Navigator>
    )
  }

  return (   
    <NavigationBar/>
  )
}
<Tab.Navigator
            screenOptions={{
                headerShown: false,
                tabBarStyle: {
                    height: 80,
                    position:'absolute',
                    backgroundColor: 'transparent',
                    elevation: 0,
                },
                tabBarLabelStyle: {color: '#000000'}
            }}
            tabBarOptions={{
                showLabel: false,
            }}>
                <Tab.Screen name="Profile" component={Profile} options={{
                tabBarIcon: ({focused}) => (
                    <View>
                        <Image
                        source={focused ? require('../assets/images/profile_use.png') : require('../assets/images/profile.png') }
                        style={{
                            width: 50,
                            height: 50,
                        }}
                        resizeMode='contain'/>
                    </View>
                ),
                }}/>
                <Tab.Screen name="Train" component={Train} options={{
                    tabBarIcon: ({focused}) => (
                        <View>
                            <Image
                            source={focused ? require('../assets/images/train_use.png') : require('../assets/images/train.png') }
                            style={{
                                width: 50,
                                height: 50,
                            }}
                            resizeMode='contain'/>
                        </View>
                    ),
                }}/>
                <Tab.Screen name="Statistics" component={Statistics} options={{
                    tabBarIcon: ({focused}) => (
                        <View>
                            <Image
                            source={focused ? require('../assets/images/statistic_use.png') : require('../assets/images/statistic.png') }
                            style={{
                                width: 50,
                                height: 50,
                            }}
                            resizeMode='contain'/>
                        </View>
                    ),
                }}/>
            </Tab.Navigator>  

解决方案

1. 完善useAuth Hook的退出逻辑

首先确保你的useAuth Hook暴露了退出登录的方法,以下是适配Firebase REST API的示例实现:

import { useState, useEffect } from 'react';

export const useAuth = () => {
  const [user, setUser] = useState(null);

  // 初始化读取本地存储的用户状态
  useEffect(() => {
    const storedUser = localStorage.getItem('user');
    if (storedUser) {
      setUser(JSON.parse(storedUser));
    }
  }, []);

  // 退出登录方法
  const logout = async () => {
    try {
      // 调用Firebase退出登录的REST接口(替换成你的API Key)
      await fetch('https://identitytoolkit.googleapis.com/v1/accounts:signOut?key=YOUR_FIREBASE_API_KEY', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ idToken: user.idToken })
      });
      // 清除本地用户信息
      localStorage.removeItem('user');
      setUser(null);
    } catch (error) {
      console.error('退出登录失败:', error);
    }
  };

  return [user, logout];
};

2. 实现Profile.js中的logOut函数

修改Profile.js,从useAuth中获取logout方法,直接调用即可,无需手动处理导航(App.js会根据user状态自动切换导航):

const Profile = () => {
  const [user, logout] = useAuth(); // 获取logout方法

  const logOut = async () => {
    await logout();
  };

  return (
    // 保持原有UI代码不变
    <View style={styles.container}>
        <View style={styles.header}>
            <Image
                source={require('../assets/images/Logo_small.png')}
                style={styles.logo_s}
                resizeMode='contain'/>
        </View>
        <View style={styles.main_cont}>
            <Profile_text marginBottom={28}/>
            <View style={styles.replace}>
              <TextInput
                style={styles.inp}
                placeholder={user.displayName}
                placeholderTextColor= 'rgba(207, 77, 79, 0.75)'
                editable={false}/>
              <Pressable onPress={''}>
                <Image
                  source={require('../assets/images/replace_btn.png')}
                  style={styles.replace_btn}
                  resizeMode='contain'/>
              </Pressable>
            </View>
            <UnderLine marginBottom={500}/>
            <Pressable style={styles.result} onPress={logOut}>
                <Text style={styles.text_result}>Выйти из профиля</Text>
            </Pressable>
        </View>
        <Image
        source={require('../assets/images/bottom_menu.png')}
        style={styles.img_bg}/>
    </View>
  )
}

3. 关键说明

你的导航结构是状态驱动的:App.js中的Navigator组件会根据user的存在与否自动切换Stack/Tab导航。调用logout后user变为null,Tab Navigator会被卸载,自动切换到登录用的Stack Navigator,不需要手动调用navigation.navigate,这也是最适配当前结构的方案。

之前手动尝试导航跳转失败,是因为退出后Tab Navigator已被卸载,无法再通过它的导航对象进行跳转,状态驱动才是正确的思路。

内容的提问来源于stack exchange,提问作者Proger228

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 22:55:17