Search code examples
iosreact-nativejsxreact-native-firebaseexpo-router

My createContext() wont work with @react-native-firebase/app


I created a useContext to access my react-native-firebase/auth gloabally.

Im runnning the app using expo run:ios I've done pod update and no errors.

None of the components are working properly anymore it was working fine when register but i don't know whats happened.

My file tree for my AuthProvider is:

and My App Screens are like this:

App Screens

I'm using expo-router and this is my package.json to my main component

"main": "expo-router/entry",

For Some reason my AuthProvider this error:

LOG: User NOT SIGNED IN

It's Also showing this error when i press on my <TextInput/>:

RemoteTextInput] -[RTIInputSystemClient
remoteTextInputSessionWithID:performInputOperation:]  perform input
operation requires a valid sessionID

I have implemented this function in my dashboard.js: ( i have imported AuthContext() )

  const { user } = useContext(AuthContext);
  const router = useRouter();

  useEffect(() => {
    if (!user) {
      console.log("User NOT SIGNED IN");
      router.push("/(home)/login"); // Redirect to login if no user
    } else {
      console.log("User SIGNED IN: ", user.email);
    }
  }, [user, router]);

This is my Redirect.js:

import React from "react";
import { Redirect } from "expo-router";


const Index = () => {
  

  if (!user) {
    // If there's no user, redirect to login
    return <Redirect href="/(home)/login" />;
  }

  // If there is a user, redirect to dashboard
  return <Redirect href="/(tabs)/dashboard" />;
};

export default Index;

My index.js:

import React from "react";
import { AuthProvider } from "../src/context/AuthProvider";
import RedirectComponent from "../components/RedirectComponent";

const Index = () => {
  return (
    <AuthProvider>
      <RedirectComponent />
    </AuthProvider>
  );
};

export default Index;

This is my AuthProvider.js:

 import React, { createContext, useState } from "react";
import auth from "@react-native-firebase/auth";
import firestore from "@react-native-firebase/firestore";

export const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);

  return (
    <AuthContext.Provider
      value={{
        user,
        setUser,
        login: async (email, password) => {
          try {
            const response = await auth().signInWithEmailAndPassword(
              email,
              password
            );
            setUser(response.user);
          } catch (error) {
            // Handle login error
            console.error("Login failed:", error);
          }
        },
        register: async (email, password) => {
          try {
            await auth()
              .createUserWithEmailAndPassword(email, password)
              .then(() => {
                //Once the user creation has happened successfully, we can add the currentUser into firestore
                //with the appropriate details.
                firestore()
                  .collection("users")
                  .doc(auth().currentUser.uid)
                  .set({
                    fname: "",
                    lname: "",
                    email: email,
                    createdAt: firestore.Timestamp.fromDate(new Date()),
                    userImg: null,
                  })
                  //ensure we catch any errors at this stage to advise us if something does go wrong
                  .catch((error) => {
                    console.log(
                      "Something went wrong with added user to firestore: ",
                      error
                    );
                  });
              })
              //we need to catch the whole sign up process if it fails too.
              .catch((error) => {
                console.log("Something went wrong with sign up: ", error);
              });
          } catch (e) {
            console.log(e);
          }
        },
        logout: async () => {
          try {
            await auth().signOut();
          } catch (e) {
            console.log(e);
          }
        },
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};

This is my _layout.js:

// ./app/(tabs)/_layout.js
import React from "react";
import AuthProvider from "../../src/context/AuthProvider";
import AppRoutes from "./(router)";

const Layout = () => {
  return (
    <AuthProvider>
      <AppRoutes />
    </AuthProvider>
  );
};
export default Layout;

Solution

  • To allow this to work i had to add a useEffect() hook into my AuthProvider.js. This updated my user variable to work within the useContext() hook

    The auth provider was placed in my function as shown in the code below:

    useEffect(() => {
        const subscriber = auth().onAuthStateChanged((user) => {
          setUser(user);
          if (user) {
            router.push("/dashboard");
          } else {
            router.push("/login");
          }
        });
        return subscriber; //
      }, []);