How do I log current user context out in firebase using Expo React Native?

73 Views Asked by At

I'm building an iOS application in React Native using Expo, and I'm using firebase to handle user creation and login. I have an AuthProvider.js class that basically allows me to set a global state (logged in/logged out) throughout the application.

Here is the AuthProvider.js

import React, { createContext, useContext, useEffect, useState } from 'react';
import { auth } from '../frontend/screens/firebase'; // Import your Firebase auth instance here

const AuthContext = createContext();

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null); // Initialize user as null

  useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged((authUser) => {
      if (authUser) {
        setUser(authUser); // Set the user if authenticated
      } else {
        setUser(null); // Set user to null if not authenticated
      }
    });

    return unsubscribe;
  }, []);

  return <AuthContext.Provider value={user}>{children}</AuthContext.Provider>;
}

export function useAuth() {
  return useContext(AuthContext);
}

Then in App.js, I've wrapped all my screens in this tag.

This seems to work fine when I login, here is the Login.js:

import React, { useEffect, useState } from 'react';
import { View, Text, TextInput, TouchableOpacity, ImageBackground, Image } from 'react-native';
import { COLORS, assets } from '../constants';
import { useNavigation } from '@react-navigation/native';
import { auth } from './firebase';

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

  useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged(user => {
      if (user) {
        navigation.navigate('Home');
      }
    });

    return unsubscribe;
  }, []);

  const handleGoBack = () => {
    navigation.goBack();
  };

  const handleSignup = () => {
    navigation.navigate('Signup'); // Navigate to the login screen
  };

  const handleLogin = () => {
    auth
      .signInWithEmailAndPassword(email, password)
      .then((userCredential) => {
        const user = userCredential.user;
        console.log('User logged in successfully:', user.email);
      })
      .catch(error => alert(error.message));
  };

  return (
    <ImageBackground
      source={assets.demoLoginImage}
      style={{
        flex: 1,
        resizeMode: 'cover',
        height: '50%',
      }}
    >
      {/* Add a button in the top left corner with an icon */}
      <TouchableOpacity onPress={handleGoBack} style={{ position: 'absolute', top: 50, left: 30, zIndex: 1, backgroundColor: COLORS.white, borderRadius: 20 }}>
        <Image source={assets.back} style={{ width: 12, height: 12, tintColor: COLORS.secondary, margin: 10 }} />
      </TouchableOpacity>
      <View
        style={{
          flex: 1,
          height: '65%',
          paddingHorizontal: 16,
          position: 'absolute',
          bottom: 0,
          left: 0,
          right: 0,
          backgroundColor: COLORS.primary,
          paddingTop: 20,
          borderTopLeftRadius: 20,
          borderTopRightRadius: 20,
          alignItems: 'center',
        }}
      >
        <Text
          style={{
            fontSize: 24,
            fontWeight: 'bold',
            marginBottom: 16,
            color: 'white',
            paddingTop: 5,
          }}
        >
          Log ind
        </Text>
        <TextInput
          style={{
            backgroundColor: 'white',
            padding: 12,
            marginTop: 20,
            marginBottom: 20,
            borderRadius: 8,
            width: '100%',
          }}
          placeholder="Email"
          keyboardType="email-address"
          autoCapitalize="none"
          onChangeText={(text) => setEmail(text)}
        />
        <TextInput
          style={{
            backgroundColor: 'white',
            padding: 12,
            marginBottom: 5,
            borderRadius: 8,
            width: '100%',
          }}
          placeholder="Password"
          secureTextEntry
          onChangeText={(text) => setPassword(text)}
        />
        <View style={{ flexDirection: 'row', justifyContent: 'flex-end', width: '100%', marginBottom: 20 }}>
          <Text
            style={{
              color: 'white',
              fontSize: 14,
              marginTop: 5,
              marginBottom: 20,
            }}
          >
            Forgot Password?
          </Text>
        </View>
        <TouchableOpacity
          onPress={handleLogin}
          style={{
            backgroundColor: COLORS.secondary,
            padding: 16,
            borderRadius: 8,
            alignItems: 'center',
            width: '100%',
          }}
        >
          <Text
            style={{
              color: 'white',
              fontSize: 18,
            }}
          >
            Log ind
          </Text>
        </TouchableOpacity>
        <View style={{ flexDirection: 'row', alignItems: 'center', marginTop: 20 }}>
          <TouchableOpacity onPress={() => handleFacebookLogin()}>
            <Image source={assets.facebook} style={{ width: 100, height: 100, marginRight: 10 }} />
          </TouchableOpacity>
          <TouchableOpacity onPress={() => handleGoogleLogin()}>
            <Image source={assets.google} style={{ width: 100, height: 100 }} />
          </TouchableOpacity>
        </View>
        <View style={{ flex: 1, justifyContent: 'flex-end', marginBottom: 20 }}>
          {/* "Log ind" and the button */}
          <View style={{ flexDirection: 'row', alignItems: 'center' }}>
            <Text style={{ color: 'white', fontSize: 16 }}>Don't have an account? </Text>
            <TouchableOpacity onPress={handleSignup}>
              <Text style={{ textDecorationLine: 'underline', color: COLORS.white, fontSize: 16 }}>Sign Up</Text>
            </TouchableOpacity>
          </View>
        </View>
      </View>
    </ImageBackground>
  );
};

export default Login;

However when I Logout, I keep getting different kind of errors. For example I've tried this:

import React from 'react';
import { View, Text, Button, SafeAreaView } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { auth } from '../screens/firebase';
import { useAuth } from '../../auth/AuthProvider'; // Import your AuthContext

const Profile = () => {
  const navigation = useNavigation();
  const { setUser } = useAuth();  // Get the setUser function from AuthContext

  const handleLogout = async () => {
    try {
      // Sign out the user using Firebase
      await auth.signOut();
      // Set user state to null
      setUser(null);
      // Navigate to a screen of your choice (e.g., Login)
      navigation.navigate('Login');
    } catch (error) {
      console.error('Logout error:', error);
    }
  };

  return (
    <SafeAreaView style={{ flex: 1 }}>
    <View>
      <Text>Profile Screen</Text>
      {/* Add your profile content here */}
      <Button title="Logout" onPress={handleLogout} />
    </View>
    </SafeAreaView>
  );
};

export default Profile;

When I click on the logout button it does log out but I get these two errors:

ERROR [TypeError: Cannot read property 'setUser' of null]
Logout error: [TypeError: setUser is not a function (it is undefined)]

0

There are 0 best solutions below