FCM Push Notifications on Expo - javascript

I am trying to implement FCM notifications for an expo react native chat app by following this documentation but I can't seem to figure out how to make it work. At some point in time I was getting an error talking about addEventListener then later a warning about unsupported browser and regarding that I read that it only allows HTTPS and localhost but I'm running in localhost:19000.
I created that firebase-messaging-sw.js even though it is empty.
App.js
import { getMessaging, getToken } from "firebase/messaging";
const Stack = createNativeStackNavigator();
const messaging = getMessaging();
getToken(messaging, {
vapidKey:
"BBDzDy5XXXXXXXXXXXXXXXXXXXXXXXVV71Df3uAY",
})
.then((currentToken) => {
if (currentToken) {
console.log("currentToken", currentToken);
} else {
console.log(
"No registration token available. Request permission to generate one."
);
Notification.requestPermission().then((permission) => {
if (permission === "granted") {
console.log("Notification permission granted.");
} else {
console.log("Unable to get permission to notify.");
}
});
}
})
.catch((err) => {
console.log("An error occurred while retrieving token. ", err);
});
function RootNavigator() {
const { user, setUser } = useContext(AuthenticatedUserContext);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
onAuthStateChanged(auth, (user) => {
setIsLoading(true);
if (user) {
setUser(user);
} else {
// console.log("out !");
}
});
setIsLoading(false);
}, [user]);
return (
<NavigationContainer>
{user ? <MainStack /> : <AuthStack />}
</NavigationContainer>
);
}
export default function App() {
return (
<AuthenticatedUserProvider>
<RootNavigator />
</AuthenticatedUserProvider>
);
}
Config.js
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import Constants from "expo-constants";
const firebaseConfig = {
apiKey: Constants.manifest.extra.apiKey,
authDomain: Constants.manifest.extra.authDomain,
projectId: Constants.manifest.extra.projectId,
storageBucket: Constants.manifest.extra.storageBucket,
messagingSenderId: Constants.manifest.extra.messagingSenderId,
appId: Constants.manifest.extra.appId,
databaseURL: Constants.manifest.extra.databaseURL,
};
// Initialize Firebase
initializeApp(firebaseConfig);
export const auth = getAuth();
export const db = getFirestore();

Related

Unable to process request due to missing initial state( Firebase)

A user of my website encountered an error message while attempting to sign up using GitHub on my React site from his chrome browser(mobile). I have integrated Firebase GitHub sign-in with the popup method.
Unable to process request due to missing initial state. This may happen if browser sessionStorage is inaccessible or accidentally cleared.
Code for signup:
import { useEffect, useState } from "react"
import { GithubAuthProvider, signInWithPopup } from "firebase/auth"
import { auth } from "../firebase/config"
import { createUserProfileDocument } from "../firebase/createUserProfileDocument"
import { useAuthContext } from "./useAuthContext"
export const useSignup = () => {
const [error, setError] = useState(false)
const [isPending, setIsPending] = useState(false)
const [isCancelled, setIsCancelled] = useState(false)
const provider = new GithubAuthProvider()
const { dispatch } = useAuthContext()
const signup = async () => {
setError(null)
setIsPending(true)
try {
const res = await signInWithPopup(auth, provider)
if (!res) {
throw new Error("Could not complete signup")
}
const user = res.user
await createUserProfileDocument(user)
dispatch({ type: "LOGIN", payload: user })
if (!isCancelled) {
setIsPending(false)
setError(null)
}
} catch (error) {
if (!isCancelled) {
setError(error.message)
setIsPending(false)
}
}
}
useEffect(() => {
return () => setIsCancelled(true)
}, [])
return { signup, error, isPending }
}
useAuthContext code:
import { useContext } from "react"
import { AuthContext } from "../context/AuthContext"
export const useAuthContext = () => {
const context = useContext(AuthContext)
if (!context) {
throw Error("useAuthContext must be used inside an AuthContextProvider")
}
return context
}
AuthContext code
import { createContext, useEffect, useReducer } from "react"
import { onAuthStateChanged } from "firebase/auth"
import { auth } from "../firebase/config"
import { authReducer } from "../reducers/authReducer"
export const AuthContext = createContext()
export const AuthContextProvider = ({ children }) => {
const [state, dispatch] = useReducer(authReducer, {
user: null,
authIsReady: false,
})
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
dispatch({ type: "AUTH_IS_READY", payload: user })
})
return unsubscribe
}, [])
return (
<AuthContext.Provider value={{ ...state, dispatch }}>{children}</AuthContext.Provider>
)
}
firebaseConfig object:
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_API_KEY,
authDomain: process.env.NEXT_PUBLIC_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_APP_ID,
measurementId: process.env.NEXT_PUBLIC_MEASUREMENT_ID,
}
initializeApp(firebaseConfig)
const db = getFirestore()
const auth = getAuth()
export { auth, db, logEvent }

Why firebase give this error when I use onSnapshot?

Error itself : Uncaught FirebaseError: Expected type 'pa', but it was: a custom $n object
firebase file :
import { initializeApp } from 'firebase/app'
import { getAuth } from 'firebase/auth'
import { getFirestore } from 'firebase/firestore/lite'
const firebaseConfig = {
apiKey: 'API_KEY',
authDomain: 'AUTH_DOMAIN',
projectId: 'PROJECT_ID',
storageBucket: 'STORAGE_BUCKET',
messagingSenderId: 'MESSAGING_SENDER_ID',
appId: 'APP_ID',
}
const firebaseApp = initializeApp(firebaseConfig)
const db = getFirestore(firebaseApp)
const auth = getAuth(firebaseApp)
export { db, auth }
Request itself :
useEffect(() => {
//getPosts()
const unsubscribe = onSnapshot(collection(db, 'cities'), (snapshot) => {
const postsList = snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
}))
setPosts(postsList)
})
return () => {
unsubscribe()
}
}, [])
I tried to change some imports like other recommend but just got another error
Firestore Lite SDK does not support listeners. Try importing getFirestore() from the standard SDK.
import { initializeApp } from 'firebase/app'
import { getAuth } from 'firebase/auth'
import { getFirestore } from 'firebase/firestore' // <-- remove /lite
const firebaseConfig = {...}
const firebaseApp = initializeApp(firebaseConfig)
const db = getFirestore(firebaseApp)
const auth = getAuth(firebaseApp)
export { db, auth }
import { db } from './path/to/firebase';
import { collection, onSnapshot } from 'firebase/firestore';
useEffect(() => {
const unsubscribe = onSnapshot(collection(db, 'cities'), (snapshot) => {
const postsList = snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
}))
setPosts(postsList)
})
}, [])

Firestore uid not available after page reload

I am exporting a function returning firestore data useing the uid as identifier. The uid however is not available after reloading the page, causing af can't read null value error. I tried researching and happened upon the shown onAuthStateChanged, but this is causing the error: TypeError: Cannot read properties of undefined (reading 'indexOf'). Would appreciate the help.
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
import {
getAuth,
onAuthStateChanged } from "firebase/auth";
import { useState, useEffect} from "react";
import {
getFirestore,
collection,
getDocs,
addDoc,
setDoc,
doc } from 'firebase/firestore';
const firebaseConfig = {
apiKey: "AIzaSyCJtckBTE3-ub4JP6NcEJX_PKao7r0YJRw",
authDomain: "dtustudenthub.firebaseapp.com",
projectId: "dtustudenthub",
storageBucket: "dtustudenthub.appspot.com",
messagingSenderId: "400034264848",
appId: "1:400034264848:web:f065a4bb76463063dd5795",
measurementId: "G-M5K2EJKLEL"
};
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
export const auth = getAuth(app);
const db = getFirestore();
export const GetAppointmentsFromFirebase = () => {
const [user, setUser] = useState({});
onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
});
const appointmentColRef = collection(db, 'users', user?.uid, 'appointments');
let [schedulerData, setSchedulerData] = useState([])
useEffect(() => {
getDocs(appointmentColRef)
.then((snapshot) => {
let appointmentData = []
snapshot.docs.forEach((doc) => {
appointmentData.push({ ...doc.data() })
})
setSchedulerData(appointmentData);
console.log(appointmentData)
})
.catch(err => {
console.log(err.message)
})
}, []);
return schedulerData;
};
You should ideally run those queries only when the user state is loaded and initialize onAuthStateChanged() in useEffect(). Try refactoring the code as shown below:
export const GetAppointmentsFromFirebase = () => {
const [user, setUser] = useState({});
let [schedulerData, setSchedulerData] = useState([])
useEffect(() => {
onAuthStateChanged(auth, async (currentUser) => {
// Check if currentUser is null
if (currentUser) {
setUser(currentUser);
// Read user ID directly from user object
const appointmentColRef = collection(db, 'users', currentUser.uid, 'appointments');
const snapshot = await getDocs(appointmentColRef)
const data = snapshot.docs.map((d) => ({
id: d.id,
...d.data()
}))
setSchedulerData(data);
console.log(data);
} else {
console.log("No user logged in")
}
});
}, []);
return schedulerData;
};

NextJS Firebase Auth undefined GoogleAuthProvider

I am having issues implementing firebase authentication with Google Provider in NextJS. I set up the environment variables and am successfully connecting to firebase. I am receiving the following error and cant seem to figure out a solution, TypeError: Cannot read properties of undefined (reading 'GoogleAuthProvider'). Below is my code.
//firebaseApp.js
import { initializeApp, getApps } from "firebase/app"
import { getFirestore } from "firebase/firestore"
import { getAuth } from "firebase/auth"
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};
if (getApps().length === 0) {
console.log('Error Connecting to Firebase')
}
const app = initializeApp(firebaseConfig)
const db = getFirestore(app)
const auth = getAuth(app)
export { db, auth }
//firebaseAuthUI.config.js
export const uiConfig = (firebase) => {
return {
signInFlow: "popup",
signInSuccessUrl: "/",
signInOptions: [firebase.auth.GoogleAuthProvider.PROVIDER_ID],
};
};
//login.js
import Head from 'next/head';
import { useRouter } from 'next/router';
import { useAuthState } from 'react-firebase-hooks/auth';
import StyledFirebaseAuth from 'react-firebaseui/StyledFirebaseAuth';
import { auth, firebase } from '../app/firebaseApp';
import { uiConfig } from '../config/firebaseAuthUI.config';
export default function Login() {
const [user, loading, error] = useAuthState(auth);
const router = useRouter();
if (loading) return 'loading'
else if (error) return error
else if (user) {
router.push('/');
}
const authConfig = uiConfig(auth);
return (
<>
<Head>
<title>Login</title>
</Head>
<StyledFirebaseAuth uiConfig={authConfig} firebaseAuth={auth} />
</>
)
}
I think the example code you copy from uses module 8
try to import GoogleAuthProvider like this, check firebase ref
import { GoogleAuthProvider} from "firebase/auth"
...
...
export const uiConfig = (firebase) => {
return {
signInFlow: "popup",
signInSuccessUrl: "/",
signInOptions: [GoogleAuthProvider.PROVIDER_ID],
};
};

GoogleAuthProvider is not a constructor

I'm still learning and I've been following tutorials on firebase auth with reactjs. Now I'm branching off into functionalities the tutorial doesn't cover (anonymous sign-in & linking to google) and I think I'm not understanding correctly how to use firebase's linkWithPopup.
I'm getting TypeError: firebase__WEBPACK_IMPORTED_MODULE_1_.default.auth.GoogleAuthProvider is not a constructor when I try do it. Here is the code:
firebase.js
import firebase from 'firebase/app';
import 'firebase/auth'
import 'firebase/firestore'
const app = firebase.initializeApp({
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_FIREBASE_APP_ID
})
export const auth = app.auth();
export default app;
AuthContext.js:
import React, { useContext, useState, useEffect } from 'react'
import firebase, { auth } from '../firebase'
const AuthContext = React.createContext();
export const useAuth = () => {
return useContext(AuthContext);
}
const AuthProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState();
const [loading, setLoading] = useState(true);
const anonLogin = () => {
return auth.signInAnonymously();
}
const linkWithGoogle = () => {
var googleProvider = new firebase.auth.GoogleAuthProvider();
auth.currentUser.linkWithPopup(googleProvider)
.then(() => {
console.log('linked correctly');
})
.catch(error => {
console.error(error);
})
}
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(user => {
setCurrentUser(user)
setLoading(false)
})
return unsubscribe
}, [])
const value = {
currentUser,
signup,
login,
logout,
resetPassword,
updateEmail,
updatePassword,
getUuid,
updateName,
anonLogin,
linkWithGoogle
}
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
);
}
}
Will appreciate any help I can get!
It looks like the Firebase reference is potentially a reference to your Firebase App rather than the Firebase library which contains the constructors for the providers.
try importing the Firebase library directly, or creating the providers inside your firebase.js file for you to export.
firebase.js
export const googleProvider = new firebase.auth.GoogleAuthProvider();
AuthContext.js
import firebase, { auth, googleProvider } from '../firebase'

Categories