Why can I not use auth.currentuser.uid in getServerSideProps? - reactjs

It may be a fundamental concept but I can't find anything to my issue.
const userDoc = getUserWithUID(auth.currentUser.uid);
Cannot read property 'uid' of null
import ImageUploader from "../components/ImageUploader";
import {auth, getUserWithUID, postToJSON} from "../lib/firebase";
import {useContext} from "react";
import {UserContext} from "../lib/context";
export async function getServerSideProps(context) {
const userDoc = getUserWithUID(auth.currentUser.uid);
return {props: {userDoc}} ;
}
export default function SettingsPage() {
return (
<main>
<ImageUploader></ImageUploader>
</main>
)
/ Firebase lib file
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import 'firebase/storage';
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
};
if(!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
export const auth = firebase.auth();
export const googleAuthProvider = new firebase.auth.GoogleAuthProvider();
export const firestore = firebase.firestore();
// Storage exports
export const storage = firebase.storage();
export const STATE_CHANGED = firebase.storage.TaskEvent.STATE_CHANGED;
export const fromMillis = firebase.firestore.Timestamp.fromMillis;
export const serverTimestamp = firebase.firestore.FieldValue.serverTimestamp;
/**`
* Gets a users/{uid} document with company
* #param {string} company
*/
export async function getUserWithCompany(company) {
const usersRef = firestore.collection('users');
const query = usersRef.where('company', '==', company).limit(1);
const userDoc = (await query.get()).docs[0];
return userDoc;
}
export async function getUserWithUID(uid) {
const userDoc = await firestore.collection('users').doc(uid).get();
return userDoc;
}

As far as my understanding goes, getServerSideProps() is only executed on the server and therefore has no access to frontEnd Data such as the Google authentication token and the corresponding userID. Hope this helps, even though you asked one month ago. :)

Related

Firestore object is sometimes undefined and sometimes works fine

I am using NextJS and Firebase fairly new to both. My app is trying to collect data from firestore database on some occasions it works fine and sometimes it returns "n is undefined" refering to the firestore object "db". This happens when i call the "collection(db, "users", uid, "posts")" function in the [posts].js file. What is causing this?
Firebase.js
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import {getStorage} from "firebase/storage"
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "xxxxxxxxxxxxxxxxxxxxxxxxx",
projectId: "xxxxxxxxxxxxxxxxxxxx",
storageBucket: "xxxxxxxxxxxxxxxxxxxx",
messagingSenderId: "xxxxxxxxxxxxxxxx",
appId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const storage = getStorage(app);
export const db = getFirestore(app);
[posts].js
import { useRouter } from 'next/router'
import { useState, useEffect } from 'react';
import Link from 'next/link';
import { useAuth } from '../context/AuthContext'
import styles from '../styles/dashboard.module.css';
import Image from 'next/image';
import { collection, getDocs } from "firebase/firestore";
import { db } from '../lib/firebase';
export default function Posts(){
const [queriedData, setQueriedData] = useState([]);
const router = useRouter()
const { uid } = router.query
useEffect(() => {
async function fetchData() {
const postsRef = collection(db, "users", uid, "posts");
const snapshot = await getDocs(postsRef);
const postData = snapshot.docs.map((doc) => {
const data = doc.data();
data.id = doc.id;
return data;
});
setQueriedData(postData);
}
fetchData();
}, []);
return(
{queriedData.map((post) =>(<div>post.title</div>)
)}
}
Added await to the collection function and I also thought it was internet issues hence i setup a firebase emulator still got the same behavior.
I tried console logging "db" right after the line "export const db = getFirestore(app);". I got out "[Object Object]"

react component not getting a return from asyncronous method

I'm working on a simple application that uses firebase for google sign on authentication. The authentication part works as far as I can because I'm getting a uid for the user. However, when I try to create a firebase database instance, and call createUserDocumentFromAuth and pass it the user that was created, I don't see the app going to the method in the console-it looks like it hangs. I put a test method in-hitThis- and I get a return from it, but not the other method.
firebase.utils.js
import {initializeApp } from 'firebase/app';
import { getFirestore, collection,doc, getDocs } from 'firebase/firestore';
import {
getAuth,
signInWithRedirect,
signInWithPopup,
GoogleAuthProvider
} from 'firebase/auth';
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "AIzaSyB8FRK9lJ8WFJa5MnCraDBTiJWN3TJCKmg",
authDomain: "ztm-react-project.firebaseapp.com",
projectId: "ztm-react-project",
storageBucket: "ztm-react-project.appspot.com",
messagingSenderId: "737539305609",
appId: "1:737539305609:web:d7a6bd52d7af973f475658"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
const provider = new GoogleAuthProvider();
provider.setCustomParameters({
prompt: "select_account"
});
export const auth = getAuth();
export const signInWithGooglePopup = () => signInWithPopup(auth,provider)
export const createUserDocumentFromAuth = async (userAuth) => {
const userDocRef = doc(db, 'users', userAuth.uid);
console.log(userDocRef);
}
export const hitThis = () =>{
console.log('hit this');
}
sign-in.component.jsx
import { signInWithGooglePopup, createUserDocumentFromAuth, hitThis} from '../../utils/firebase/firebase.utils';
const SignIn = () =>{
hitThis();
const logGoogleUser = async () => {
const user = await signInWithGooglePopup();
createUserDocumentFromAuth(user);
}
return(
<div>
<h1>Sign In Page</h1>
<button onClick={logGoogleUser}>Sign in with Google Popup</button>
</div>
);
}
export default SignIn
Your createUserDocumentFromAuth function doesn't call any API that writes data, so that'd explain why you don't see any result in the database. To actually write data, call setDoc as shown in the documentation on writing data to a new document reference.

Reactjs Firebase: Uncaught TypeError: (0 , _config_firebase__WEBPACK_IMPORTED_MODULE_2__.default) is not a function

I'm pretty new to react and firebase. I implemented a login/auth system with firebase, and I was trying to take this to the next level: implement a profile page with profile picture. I followed a youtube tutorial and it seemed pretty easy,but somehow I'm getting a firebase error, and I assume something changed since the release of that tutorial! I don't really know what is going on, please help me fix this and explain me like I'm 5!
(update profile picture file)
ProfilePicture.js:
import React, {useEffect, useState} from 'react'
import {useAuth} from '../authentication/AuthContext'
import upload from '../../config/firebase'
export default function ProfilePicture() {
const currentUser = useAuth()
const [photo, setPhoto] = useState(null)
const [loading, setLoading] = useState(false)
const [photoURL, setPhotoURL] = useState("https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png")
function handleChange(e){
if (e.target.files[0]){
setPhoto(e.target.files[0])
}
}
function handleClick(){
upload(photo, currentUser, setLoading)
}
useEffect(()=>{
if (currentUser && currentUser.photoURL){
setPhotoURL(currentUser.photoURL)
}
}, [currentUser])
return (
<>
<input type="file" onChange={handleChange} />
<button disabled={loading || !photo} onClick={handleClick}>Upload</button>
<img src={photoURL} alt="Avatar" className='avatar'/>
</>
)
}
firebase.js
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
import 'firebase/firestore'
import { getStorage, ref, uploadBytes } from 'firebase/storage';
const app = firebase.initializeApp({
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
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 = firebase.auth();
export const firestore = firebase.firestore();
export const storage = getStorage();
//storage
export async function upload(file, currentUser, setLoading){
const fileRef = ref(storage, currentUser.uid + '.png')
setLoading(true)
const snapshot = await uploadBytes(fileRef, file)
setLoading(false)
alert("Uploaded File!")
}
export const createUserDocument = async (user, additionalData) => {
if (!user) return;
const userRef = firestore.doc(`users/${user.uid}`);
const snapshot = await userRef.get();
if (!snapshot.exists) {
const { email } = user;
const { displayName } = additionalData;
try {
await userRef.set({
displayName,
email,
createdAt: new Date(),
});
} catch (error) {
console.log('Error creating user', error);
}
}
};
export default app
the error:
You are mixing up firebase compat version with the latest firebase modular version
The following lines are not needed.
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
import 'firebase/firestore'
https://firebase.google.com/docs/web/modular-upgrade
You may want to revisit the documentation, and only follow the codes under version 9 modular.
For example, to initialize the app, the correct codes for version 9 modular will be something like this.
import { initializeApp, getApps } from "firebase/app"
var firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECTID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGEBUCKET,
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
};
For authentication you need to use getAuth
For example
import firebase from 'src/firebase/firebase'
import { getAuth, signInWithEmailAndPassword } from "firebase/auth";
const auth = getAuth(firebase);
export async function loginPassword(email, password) {
return await signInWithEmailAndPassword(auth, email,password)
}
Reference: https://firebase.google.com/docs/auth/web/password-auth
Please follow the codes from v9 modular

error - ReferenceError: Cannot access 'auth' before initialization

so I am following this online tutorial on how to build a WhatsApp build and I ran into this problem.
import "../styles/globals.css";
import { useAuthState } from "react-firebase-hooks/auth";
import { auth, db } from "../firebase";
function MyApp({ Component, pageProps }) {
const [user] = useAuthState(auth);
if (!user) return <Login />;
return <Component {...pageProps} />;
}
export default MyApp;
This is my firebase.js, I removed the my apiKey because I am sharing my code but that don't think that is the issue.
import firebase from "firebase/app";
const firebaseConfig = {
apiKey: "",
authDomain: "global-chat-80ab3.firebaseapp.com",
projectId: "global-chat-80ab3",
storageBucket: "global-chat-80ab3.appspot.com",
messagingSenderId: "405392556419",
appId: "1:405392556419:web:562d012b108561b8be76b6",
};
const app = !firebase.apps.length
? firebase.initializeApp(firebaseConfig)
: firebase.app();
const db = app.firestore();
const auth = app.auth();
const provider = new firebase.auth.GoogleAuthProvider();
export { db, auth, provider };
I'm using firebase v9 modular code as in firebase Documentation
Firebase Version: 9.6.1
This code worked fine for me. But the downside I faced was v9 modular functionalities won't work with react-firebase-hooks.(Not supported till now I guess)
My usecase: for next.js project with firebase.
import { initializeApp, getApps } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth";
import { GoogleAuthProvider } from "firebase/auth";
const firebaseConfig = {
apiKey: "",
authDomain: "global-chat-80ab3.firebaseapp.com",
projectId: "global-chat-80ab3",
storageBucket: "global-chat-80ab3.appspot.com",
messagingSenderId: "405392556419",
appId: "1:405392556419:web:562d012b108561b8be76b6",
};
// Initialize Firebase
const app = getApps().length === 0 ? initializeApp(firebaseConfig) : getApps();
const auth = getAuth();
const db = getFirestore();
const provider = new GoogleAuthProvider();
export { db, auth, provider };
If you're using Firebase 9.6.0, try updating your imports to v9 compat. This recommendation comes from the Firebase documentation.
So, your imports would look like this:
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
const firebaseConfig = {
apiKey: "",
authDomain: "global-chat-80ab3.firebaseapp.com",
projectId: "global-chat-80ab3",
storageBucket: "global-chat-80ab3.appspot.com",
messagingSenderId: "405392556419",
appId: "1:405392556419:web:562d012b108561b8be76b6",
};
const app = !firebase.apps.length
? firebase.initializeApp(firebaseConfig)
: firebase.app();
const db = app.firestore();
const auth = app.auth();
const provider = new firebase.auth.GoogleAuthProvider();
export { db, auth, provider };

React Native authentication and cloud Firestore for web apps

I am new to both Firebase and React so bear with me here.
I am trying to use cloud Firestore and Authentication in my application but am a little unsure on how to set up my firebase.js file. I have scaled the internet and watched plenty of videos/tutorials but can't seem to figure out how to implement these into my app. It also seems that some tutorials that I watched from 2020 are not out of date.
Here's my code:
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
// import { getAuth, signInWithCustomToken } from "firebase/auth";
const firebaseConfig = {
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
};
// const auth = getAuth();
// signInWithCustomToken(auth, token)
// .then((userCredential) => {
// // Signed in
// const user = userCredential.user;
// // ...
// })
// .catch((error) => {
// const errorCode = error.code;
// const errorMessage = error.message;
// // ...
// });
const app = initializeApp(firebaseConfig);
const db = getFirestore(app)
// export const auth = app.auth()
export { db }
You can export the auth instance from firebase.js and then use it in any component you need. Assuming you have a login component:
firebase.js:
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth"
const app = initializeApp(firebaseConfig);
const db = getFirestore(app)
const auth = getAuth(app)
export { db, auth }
login.jsx:
// login component
import { auth } from "./firebase.js"
import { signInWithEmailAndPassword } from "firebase/auth"
// run on button click or relevant events
signInWithEmailAndPassword(auth, email, password).then((user) => {
console.log(user)
})

Resources