Self taught coder here. Hopefully I'm explaining the issue adequately.
I'm trying to create some user authentication using firebase. I keep getting an error saying "Line 18:16: 'getAuth' is not defined". I'm confused because I was following a tutorial. I have tried reordering my imports as I read online that might be the reason for the error. For some reason I think my problem is in the config file and how I've initialized everything. I'm new to firebase. Any potential solves would be appreciated.
Here is my firebase.js config
import { initializeApp } from "firebase/app";
import { getFirestore } from 'firebase/firestore'
import { getAuth } from "firebase/auth";
import "firebase/storage"
const firebaseConfig = {
apiKey: "process.env.REACT_APP_FIREBASE_KEY",
authDomain: "uploadimg.firebaseapp.com",
projectId: "uploadimgofficial",
storageBucket: "uploadimg.appspot.com",
messagingSenderId: "MESSENGER_ID",
appId: "APP_ID",
measurementId: "MESAUREMENT_ID"
};
const app = initializeApp(firebaseConfig);
export const auth = getAuth()
// Init firestore
const db = getFirestore()
export { db }
And this is where I'm trying to set up the login page
import React from "react";
import "./Login.scss";
import { useState } from "react";
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from "../../firebase";
const Login = () => {
const [error, setError] = useState(false);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const handleLogin = (e) => {
e.preventDefault();
};
const auth = getAuth(); // <------ THIS IS ERROR LINE
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
console.log(user)
})
.catch((error) => {
setError(true)
});
return (
<div className="login">
<form onSubmit={handleLogin} className="login__form">
<input
className="login__email"
onChange={e => setNewEmail(e.target.value)}
type="email"
placeholder="email" />
<input
The issue with your code is that you have imported the getAuth function incorrectly.
To fix this, you need to correct the name usage when calling the function.
As you have imported getAuth as auth in the import statement at the top of your file, you need to use it as so.
import { auth } from "../../firebase.js";
Right now, you are importing the auth variable, which is set to the return value of getAuth, as defined below in the firebase.js file.
// As you are calling the function with '()', you are getting the return value.
export const auth = getAuth();
To fix this, simply change your function call to auth. Also, rename the variable to something other than auth to avoid name collisions, and/or confusing naming patterns.
Also, as you are getting and setting the return value of getAuth to auth, the return value may not be a function1. In that case, you can't call auth with brackets (()), as, for instance, it may return an object.
// Change the variable name to what you want.
const userAuth = auth;
To check if it is a string/object/function/etc, you can use typeof (for checking/debugging; remove this line once done).
console.log(typeof auth); // Should return: 'string' | 'function' | 'object' | ...
Depending on the return type, you can change your usage to match it.
In conclusion, to fix your issue, you need to correctly use the name (auth instead of getAuth). Also, make sure to check the return value of getAuth, and use it appropriately!
1 Please correct me in the comments if I am incorrect; the return value is a function. In that case, I can remove that part. Thank you for the clarification!
Related
I am trying to set up Firebase with next.js. I am getting this error in the console.
FirebaseError: Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore
This is one of my custom hook
import { onAuthStateChanged, User } from '#firebase/auth'
import { doc, onSnapshot, Unsubscribe } from 'firebase/firestore'
import { useEffect, useState } from 'react'
import { auth, fireStore } from './firebase'
export const useUserData = () => {
const [username, setUsername] = useState<string | null>(null)
const [currentUser, setCurrentUser] = useState<User | null>(null)
useEffect(() => {
let unsubscribe: void | Unsubscribe
onAuthStateChanged(auth, (user) => {
if (user) {
setCurrentUser(user)
// The Problem is inside this try blog
try {
// the onsnapshot function is causing the problem
console.log('firestore: ', fireStore)
unsubscribe = onSnapshot(doc(fireStore, 'users', user.uid), (doc) => {
setUsername(doc.data()?.username)
})
} catch (e) {
console.log(e.message)
}
} else {
setCurrentUser(null)
setUsername(null)
}
})
return unsubscribe
}, [currentUser])
return { currentUser, username }
}
I also have this firebase.ts file where I initialized my firebase app
import { FirebaseApp, getApps, initializeApp } from 'firebase/app'
import { getAuth } from 'firebase/auth'
import { getFirestore } from 'firebase/firestore/lite'
import { getStorage } from 'firebase/storage'
const firebaseConfig = {
apiKey: 'some-api',
authDomain: 'some-auth-domain',
projectId: 'some-project-id',
storageBucket: 'some-storage-bucket',
messagingSenderId: 'some-id',
appId: 'some-app-id',
measurementId: 'some-measurement-id',
}
let firebaseApp: FirebaseApp
if (!getApps.length) {
firebaseApp = initializeApp(firebaseConfig)
}
const fireStore = getFirestore(firebaseApp)
const auth = getAuth(firebaseApp)
const storage = getStorage(firebaseApp)
export { fireStore, auth, storage }
I don't know whether the problem is in the project initialization. I am pretty sure the error is generated from my custom hook file. I also found out that there must be something wrong with onSnapshot function. Am I passing the docRef wrong or something? What am I doing wrong here?
The console.log(firestore) log:
type: "firestore-lite"
_app: FirebaseAppImpl
_automaticDataCollectionEnabled: false
_config: {name: "[DEFAULT]", automaticDataCollectionEnabled: false}
_container: ComponentContainer {name: "[DEFAULT]", providers: Map(15)}
_isDeleted: false
_name: "[DEFAULT]"
_options:
apiKey: 'some-api'
authDomain: 'some-auth-domain'
projectId: 'some-project-id'
storageBucket: 'some-storage-bucket'
messagingSenderId: 'some-id'
appId: 'some-app-id'
measurementId: 'some-measurement-id'
[[Prototype]]: Object
automaticDataCollectionEnabled: (...)
config: (...)
container: (...)
isDeleted: (...)
name: (...)
options: (...)
[[Prototype]]: Object
_credentials: Q {auth: AuthInterop}
_databaseId: H {projectId: "next-firebase-fireship", database: "(default)"}
_persistenceKey: "(lite)"
_settings: ee {host: "firestore.googleapis.com", ssl: true, credentials: undefined, ignoreUndefinedProperties: false, cacheSizeBytes: 41943040, …}
_settingsFrozen: false
app: (...)
_initialized: (...)
_terminated: (...)
Using getFirestore from lite library will not work with onSnapshot. You are importing getFirestore from lite version:
import { getFirestore } from 'firebase/firestore/lite'
Change the import to:
import { getFirestore } from 'firebase/firestore'
From the documentation,
The onSnapshot method and DocumentChange, SnapshotListenerOptions, SnapshotMetadata, SnapshotOptions and Unsubscribe objects are not included in lite version.
Another reason for this error to show up could be passing invalid first argument to collection() or doc() functions. They both take a Firestore instance as first argument.
// Ensure that "db" is defined and initialized
const db = getFirestore();
// console.log(db);
const colRef = collection(db, "collection_name");
Don't mix usage of firestore/lite with firestore
You need to use in your imports either:
'firebase/firestore'
OR
'firebase/firestore/lite'
Not both in the same project.
In your case, the firebase.ts file is using:
import { getFirestore } from 'firebase/firestore/lite'
And in your hook:
import { doc, onSnapshot, Unsubscribe } from 'firebase/firestore'
So you're initialising the lite but using the full version afterwards.
Keep in mind that both has it's benefits, but I would suggest in your case to pick one and just use it. Then the error will be gone.
Adding to #Dharmaraj, if you are using firebase react hooks, use the reverse.
Instead of
import { getFirestore } from 'firebase/firestore'
Use
import { getFirestore } from 'firebase/firestore/lite'
If you are using firebase lite then collection is not used.
Firebase lite example:
import {
getFirestore,
getDoc,
updateDoc,
doc
} from '#firebase/firestore/lite';
const firestore = getFirestore(app);
const docRef = doc(firestore, 'collection/doc');
const docSnap = await getDoc(docRef);
await updateDoc(docRef, "field", 'value');
When to use Firestore Lite
It can be tricky to decide when to let go of the standard Firestore SDK's offline persistence and caching features. You should understand these features before deciding to trade them away for the lower overhead of Firestore Lite. In general, weigh these factors when deciding whether to use Firestore Lite:
Online status - Firestore Lite is good for apps that do not need live updates and have connectivity.
Size constraints - Firestore Lite is great if you want to reduce your overall JavaScript bundle size.
Read more here
This can happen if you have both #firebase/firestore and firebase installed and there is a version mismatch.
firebase comes with #firebase/firestore. Remove any #firebase/... dependencies so that you're using the same version that firebase uses.
I'm uploading a user profile image into firebase storage, then updating the photoURL value of the auth user with updateProfile(). After that I want the user to be updated without manually refreshing the page. I've been trying this for days now and the issue gets more weird every time I try to debug it.
The interesting thing is the user object seems to be already updated when I log it with console.log(currentUser) after the then promise of updateProfile() is fulfilled. So the new photoURL is already present in the currentUser object. But it seems to not call a state update or console.log("!!!!currentAuthUserUpdate", user);. So the user image wouldn't refresh in my page.
I even tried it with doing a useEffect with the currentUser as a dependency but it wasn't fired. Still, the currentUser object changed when logging it after updateProfile()
Updating the profile, UpdateUserImage.tsx:
import { useAuth } from "../../contexts/AuthContext";
const { currentUser } = useAuth();
// updating the user profile
updateProfile(currentUser, { photoURL })
AuthContext.tsx:
import { auth } from "./../firebase/firebase";
const [currentUser, setCurrentUser] = useState(null);
const auth = getAuth(app);
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
console.log("!!!!currentAuthUserUpdate", user);
// I tried setting the user as a custom new object: const userData = { ...user };
setCurrentUser(user);
});
return unsubscribe;
}, []);
firebase.js
import { getAuth } from "firebase/auth";
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
export {
auth
};
What I tried additionally: (But this wouldn't work as the user is already updated without a state refresh from react, so it's trying to replace the same object)
const reloadUser = async () => {
try {
const res = await currentUser.reload();
const user = auth.currentUser;
console.log("currentUser:", user);
setCurrentUser(auth.currentUser);
console.log("res", res);
} catch (err) {
console.log(err);
}
};
it's not auth.onAuthStateChanged. You need to import onAuthStateChanged from 'firebase/auth'
import { getAuth, onAuthStateChanged } from "firebase/auth"
const auth = getAuth(); // leave getAuth empty if you only have one app
Then in your useEffect it should be
onAuthStateChanged(auth, async (currentUser) => { ... }
The setCurrentUser function returned from useState isn't always the same function in my experience.
You can try passing it as a dependency into the useEffect - but I don't think that's what you want.
React lets you use an old useState setter if you give it an updater function, rather than a value: setCurrentUser(()=>auth.currentUser)
The React docs dispute this though.
Using useStates are good for re-rendering components. However going into utilizing useRefs are best for updating the actual variable and will not cause a re-render of the component.
Declare it like:const currentUser = useRef(null)
Update it like: currentUser.current = updatedUserData
Use in code like: currentUser.current.photoURL
Inside my index.js file:
export function postArticleAPI(payload) {
return(dispatch) => {
const upload = storage
.ref(`images/${payload.image.name}`)
.put(payload.image);
upload.on("state_changed", (snapshot) => {
const progress = (
(snapshot.BytesTransferred / snapshot.totalBytes) * 100);
console.log(`Progress: ${progress}%`);
if(snapshot.state === "RUNNING") {
console.log(`Progress: ${progress}%`);
}
},
(error) => console.log(error.code),
async() => {
const downloadURL = await upload.snapshot.ref.getDownloadURL();
db.collection("articles").add({
...
});
});
}
};
}
I look in the docs provided by firebase but I am unsure how to implement that. When I run the code above, I get "TypeError: firebase__WEBPACK_IMPORTED_MODULE_0_.storage.ref is not a function" error.
I messed around with the code and I've also gotten other errors such as: "...storage.put is not a function," I've gotten errors with upload, as well as db.collection error.
Here's my firebase.js:
import { initializeApp } from 'firebase/app';
import { getAuth, GoogleAuthProvider } from 'firebase/auth';
import { getStorage } from "firebase/storage";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
...
}
const firebaseApp = initializeApp(firebaseConfig);
const db = getFirestore(firebaseApp);
const auth = getAuth();
const provider = new GoogleAuthProvider();
const storage = getStorage(firebaseApp);
export { auth, provider, storage };
export default db;
Any help would be appreciated (and this is my first post, so please let me know if I need to add anything else). Thanks!
Since you're using the v9 syntax for importing top-level functions, there is no longer a storage.ref() method. Instead, as shown in the documentation on getting a reference and uploading files, you can do:
const ref = ref(storage, `images/${payload.image.name}`)
const upload = uploadBytes(ref, payload.image);
I have a code that is a form, basically is suppose to update the user information.
According to Firebase documentation manage user but for some reason I'm getting this errors
This is what I have I don't think I'm missing anything is pretty much the same
The only difference is that on my firebase.js I made new cons to make codes shorter but that shouldn't affect at all.
firebase.js
const db = firebase.firestore();
const auth = firebase.auth();
const storage = firebase.storage();
export {db, auth, storage};
Code
import {auth} from "./firebase"
const authUser = auth.currentUser
const update = (e) => {
e.preventDefault();
authUser.updateProfile({
displayName: {fullName}
})
}
I just wanted to test it on the user name first and then do all the others but I don't understand why is not working is super simple.
Update
authUser is undefined. This means that auth.currentUser was undefined at the time when it was assigned to authUser. This probably means that the user is not logged in. You will need to handle the case when the user is not logged in, like
import {auth} from "./firebase"
const authUser = auth.currentUser
const update = (e) => {
e.preventDefault();
if (authUser) {
authUser.updateProfile({
displayName: fullName
})
} else {
//User is not logged in, handle that case here
}
}
import {auth} from "./firebase";
const authUser = auth.currentUser;
const update = (e) => {
e.preventDefault();
authUser?.updateProfile({
displayName: fullName
});
}
I am trying to use Firebase Authentication on my Next.js website. For some reason, when I press the sign up button, nothing happens and no errors are logged. It just refreshes the page. It doesn't even set any cookies or create a user.
Here are my two files related to authentication:
utils/authProvider.js:
import firebase from 'firebase/app';
import 'firebase/auth';
if(!firebase.apps.length) {
firebase.initializeApp({
// config
});
}
const auth = firebase.auth();
module.exports = { auth };
pages/signup.js:
import { useState } from 'react'
import { LockClosedIcon } from '#heroicons/react/solid'
import { auth } from '../utils/authProvider'
export default function CreateAccount() {
const [emailField, setEmailField] = useState('');
const [passwordField, setPasswordField] = useState('');
// emailField and passwordField are set correctly, I used console.log to test it
const createAccount = () => {
// this event does get triggered, I used console.log to test it
auth.createUserWithEmailAndPassword(emailField, passwordField)
.then((userCredential) => {
window.location.replace('/');
console.log('logged in!');
}).catch((error) => {
console.error(error);
});
}
Edit: After experimenting some more, I saw that the request to https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser never gets completed. It just shows as red in the network traffic tab of Chrome dev tools. Any reason why this might happen?
Thanks in advance.