The code below is a component within nextjs with the purpose of writing data to a firestore database after the user clicks a button.
Firebase isn't writing my data to the firestore database, however the alert within my callback (that is after the supposed datadump) works. i tried checking over my process.env file to see if that's where the problem was, but that wasn't the issue.
heres my write file
import firebase from 'firebase/app'
import 'firebase/firestore'
const WriteToCloudFirestore = () => {
const sendData = () => {
try {
//send data
firebase
.firestore()
.collection('myCollection')
.doc('my_document')
.set({
string_data: 'string',
more_data: 123
})
.then(alert('data sent to firestore'))
}
catch(e) {
console.log(e)
alert(e)
}
}
return (
<>
<button onClick={sendData}>send data to cloud firestore</button>
</>
)
}
export default WriteToCloudFirestore
if you are in need of anymore files I can add them, but as far as I'm aware firebase has been initalized on my app. I looked through some other questions on this forum and was able to find a very similar problem that had to do with the data returning null - but I don't see how that's my issue because I am placing data in my .set portion of the firestore code.
Javascipt alerts are synchronous that means it'll block any code execution unless the alert is dismissed. The moment you dismiss the alert your data will pop up in Firestore. Therefore, you should handle the promise returned by Firestore set method first and then show the alert.
firebase
.firestore()
.collection("myCollection")
.doc("my_document")
.set({
string_data: "string",
more_data: 123,
})
.then(() => {
console.log("Data addded")
alert("data sent to firestore")
})
.catch((e) => console.log(e));
Alternatively you can use async-await syntax:
const sendData = async () => {
console.log("Sending Data");
try {
await firestore.collection("myCollection").doc("my_document").set({
string_data: "string",
more_data: 123,
})
alert("Data added to Firestore")
} catch (e) {
console.log(e)
}
}
You can read more about that behaviour in this blog.
Related
I'm trying to add MFA inside my web app following the guide https://cloud.google.com/identity-platform/docs/web/mfa.
I started with enrolling the phone number successfully with the account and now when I want to "login" again using that phone number but I can’t use the number to get a code.
Check the code:
//I have imported my firebase services inside services/firebase.js
import { auth, signInWithEmailAndPassword, PhoneMultiFactorGenerator } from '#/services/firebase';
methods: {
//On login button click - this method is called
login: async function (event) {
var self = this;
await signInWithEmailAndPassword(auth, self.user_email, self.user_password)
.then(()=> {
...
//I am setting the user here, and giving access based on the role of the user
}
.catch((error) => {
console.log('Error:', error);
//Gives: Error: FirebaseError: Firebase: Error (auth/multi-factor-auth-required).
if (error.code == 'auth/multi-factor-auth-required') {
self.resolver = error.resolver;
//assigning to my data field so I can use this later with my phone number verification
console.log(error.resolver);
//UNDEFINED
...
} else {
...
}
});
}
}
In the code above the error object does not have a resolver, so "error.resolver" is undefined which I need in a later stage.
(FYI:- I am not using the Multi-Tenancy option)
UPDATE: Solved
The docs (https://cloud.google.com/identity-platform/docs/web/mfa) are outdated and functions are changed now.
Now the resolver doesn't come from the error object, we just need to call the resolver using a firebase function
getMultiFactorResolver
resolver = getMultiFactorResolver(auth, error);
Have a look here and you will undestand everything: https://firebase.google.com/docs/reference/js/auth.multifactorresolver#example_2
I am not able to transfer user input which is stored in a AsyncStorage to my MongoDB database
I have a MongoDB database which I start from the terminal. The console output is the following so there should not be any problems:
Server started on PORT 5000
MongoDB Connected cluster0-shard-00-02.mhqqx.mongodb.net
After this I open my React Native app with expo go and go to my register screen where a new user profile should be created. I store every required user input (name, email, etc.) in a AsyncStorage in JSON format like this:
const nameString = JSON.stringify(name)
const emailString = JSON.stringify(email)
AsyncStorage.setItem('nameInput', nameString);
AsyncStorage.setItem('emailInput', emailString);
setName('');
setEmail('');
When I print the values of the AsyncStorages in the console, there is no error and the data is displayed correctly. So the user inputs are stored in the AsyncStorages.
But after this I try to transfer the AsyncStorage data to my MongoDB database by triggering the following function with a button onPress call:
const submitHandler = async (e) => {
if(password !==confirmpassword) {
setMessage('Passwords do not match')
} else {
setMessage(null)
try {
const config = {
headers: {
"Content-type": "application/json",
},
};
setLoading(true);
const { data } = await axios.post(
"/api/users",
{name, email, password},
config
);
setLoading(false);
} catch (error) {
setError(error.response.data.message);
}
}
console.log(email);
};
When I check the database, no new information is displayed in my database. The database is functional and the route which is defined should be correct. What could be the problem?
I am also able to create a new user from Postman like this:
I have tried to search some answers for this problem for a while now but without success. Help would be much appreciated!
You can do something like
await axios.post("/api/users",
{name, email, password},config)
.then(res=> console.log(res)
.catch(err => console.log("api error", err)
And see what you get in your corresponding terminal.
Note
Your API endpoint(api/users) is not valid. Add the same URL from Postman which you're using.
With VueJS and Firebase, I want to create a user and then if it succeed add more info to a users collection.
Problem is my variable usersCollection is undefined when I get in the .then. I know I can take that exact code out of the .then and it works. Also, the auth function works as it is supposed to. It would seem that the problem is that I'm trying to access the collection inside the .then. But then again, I need to do this only if I successfully create a new user for authentication to avoid having users info from unregistered users. I don't enter the .catch either and I don't get an error of any kind in the chrome console. Any idea how to get this logic to work?
I initialize everything about firebase with this :
import * as firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/firestore'
import 'firebase/analytics'
const firebaseConfig = {
//configs
};
firebase.initializeApp(firebaseConfig);
firebase.analytics();
const db = firebase.firestore();
const auth = firebase.auth();
const usersCollection = db.collection('users');
export {
db,
auth,
usersCollection
}
The code is located in the main store of the app :
import * as types from './types';
import {
auth,
usersCollection,
} from '../../../../config/firebase';
//...
[types.ADD]: ({commit}, user) => {
auth.createUserWithEmailAndPassword(user.email, user.password)
.then((e) => {
usersCollection.add(user)
.then((docRef) => {
commit(types.MUTATE_ADD, user);
console.log("Document written with ID: ", docRef.id);
})
.catch((error) => {
console.error("Error adding document: ", error);
});
})
.catch((e) => {
//...
alert('An error occured while creating employee.\n' + e.code + '\n' + e.message);
return false;
});
}
Above, the the user I use for authentication is created, but when I get to the .then usersCollection is undefined, yet I get no error in the Chrome console and the user is not created.
As explained earlier, if I take the block where I add the user to the collection out of the .then I get to add the user to the collection :
[types.ADD]: ({commit}, user) => {
auth.createUserWithEmailAndPassword(user.email, employeeHelper.makePassword(user))
.then((e) => {
})
.catch((e) => {
var errorCode = e.code;
var errorMessage = e.message;
alert('An error occured while creating employee.\n' + e.code + '\n' + e.message);
return false;
});
usersCollection.add(user)
.catch((error) => {
console.error("Error adding document: ", error);
});
}
Using another method made it work exactly as I intended :
[types.ADD]: ({commit}, user) => {
commit(types.MUTATE_ADD, user);
auth.createUserWithEmailAndPassword(user.email, employeeHelper.makePassword(user))
.then((e) => {
usersCollection.doc(user.email).get().then((querySnapshot) => {
querySnapshot.ref.set(user).then(() => {
//log success
})
}).catch((e) => {
console.log(e);
//log error
})
})
.catch((e) => {
//log error
return false;
});
}
The difference is that instead of using .add() method on my usersCollection, I used .doc(user.email).get().then(...) and I set data afterwards instead of using .add(...). For some reason, the Chrome console still shows usersCollection as if it is undefined if I put a breakpoint there :
usersCollection.doc(user.email).get().then((querySnapshot) => {
But the data is properly pushed to firestore nonetheless. So I'm not completely comfortable with the fact that I don't know why it works this way but not the other, but the result is exactly what I needed even though I suspect it creates some overhead.
I am trying to update the email of the current user, I went to documentation and I copied the example code that they are given there,
But nothing worked, this from doc didn't work
var user = firebase.auth().currentUser;
user.updateEmail("newemail#example.com").then(function() {
console.log('success')
}).catch(function(error) {
console.log('failed')
});
I have also tried :
try {
await user.updateEmail('test#test.com').then(function() {
console.log('success')
}).catch(function(error) {
handleErrors(dispatch, error.message);
});
} catch(e) {
handleErrors(dispatch, e.message);
}
could you help to solve this issue?
update :
sorry i didn't include the exact error that come out in the console , here is the error :
This operation is sensitive and requires recent authentication. Log in
again before retrying this request.
2)
I should add that I am using asyncstorage of react native , and I store that Item( profile of user => email , name , ect..) in reduxPersist
that how my login code is :
export const login = ( email, password ) => {
return async (dispatch) => {
dispatch({ type: ATTEMPTING });
try {
await firebase.auth().signInWithEmailAndPassword(email, password)
.then(resp => handleLoginSuccess(dispatch, resp.uid,resp.name,email))
.catch(error => handleErrorLogin(dispatch, error.message));
}catch(e){
handleErrorLogin(dispatch, e.message);
}
};
};
const handleLoginSuccess = async(dispatch , userId,name,email) => {
try{
const profile = { userId, name, email };
await AsyncStorage.setItem('userProfile', JSON.stringify(profile));
dispatch({ type: LOGIN_SUCCESS, payload: profile });
}catch(e){
alert(e.message);
}
}
The error message is telling you that there is no user logged in at the time you call updateEmail. The SDK doesn't know which user you're trying to modify. You'll need to wait until the login is fully complete before calling that method.
Note that all of the Firebase APIs are asynchronous, so you'll need to make use of their returned promises to make sure the order of calls is valid.
While i click on the login button i get this error :
[19:49:11] [2018-12-25T20:49:57.389Z] #firebase/database:, FIREBASE
FATAL ERROR: Cannot parse Firebase url. Please use https://<YOUR
FIREBASE>.firebaseio.com
- node_modules/#firebase/logger/dist/index.cjs.js:69:32 in
defaultLogHandler
- node_modules/#firebase/logger/dist/index.cjs.js:159:31 in error
- node_modules/#firebase/database/dist/index.cjs.js:333:20 in fatal
- node_modules/#firebase/database/dist/index.cjs.js:1256:14 in
parseRepoInfo
- node_modules/#firebase/database/dist/index.cjs.js:15103:38 in
refFromURL
* src/modules/auth/api.js:24:24 in getUser
* src/modules/auth/api.js:19:32 in <unknown>
- node_modules/#firebase/auth/dist/auth.js:17:105 in <unknown>
- node_modules/#firebase/auth/dist/auth.js:20:199 in Fb
- ... 13 more stack frames from framework internals
I copied and pasted the config stuff directly from Firebase, so it should be correct, but I get this error anyway. What could be causing this? Is there any way the URL I'm copying from my database could be wrong somehow?
As you you can see in the error shown are in my file api.js in
.then((user) => getUser(user, callback))
and in
database.refFromURL('users').child(user.uid).once('value')
So here is my code from api.js is like this :
import { auth, database, provider } from "../../config/firebase";
export function register(data, callback) {
const { email, password } = data;
auth.createUserWithEmailAndPassword(email, password)
.then((user) => callback(true, user, null))
.catch((error) => callback(false, null, error));
}
export function createUser (user, callback) {
database.refFromURL('users').child(user.uid).update({ ...user })
.then(() => callback(true, null, null))
.catch((error) => callback(false, null, {message: error}));
}
export function login(data, callback) {
const { email, password } = data;
auth.signInWithEmailAndPassword(email, password)
.then((user) => getUser(user, callback))
.catch((error) => callback(false, null, error));
}
export function getUser(user, callback) {
database.refFromURL('users').child(user.uid).once('value')
.then(function(snapshot) {
const exists = (snapshot.val() !== null);
if (exists) user = snapshot.val();
const data = { exists, user }
callback(true, data, null);
})
.catch(error => callback(false, null, error));
}
can anyone please help where i missed up
i used
database.ref(`users/`+user.uid).once('value')
instead of
database.refFromURL('users').child(user.uid).once('value')
and it works fine for me now.
Please go through this documentation and update to new modular type or if you want to use old structure then, update to
<script src="https://www.gstatic.com/firebasejs/8.5.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.5.0/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.5.0/firebase-database.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.5.0/firebase-storage.js"></script>
update all to version 8.5.0. Will work flawless
The refFromURL method expects a fully qualified URL to the database. So something starting with https://<YOUR
FIREBASE>.firebaseio.com as the error message shows.
You're trying to access a path within the configured database, in which case you should use ref(...) instead:
database.ref('users').child(user.uid).once('value')
I think there are mainly two types of realtime db urls , one ends with ".firebaseio.com" which is for US and other like EU and asia have url which ends with "firebasedatabase.app"
"Please use https://.firebaseio.com", this error comes at line when u call firebase.database(), It can happen that firebase library or module you are using are of old versions which can only make call for db whose url ends with firebaseio.com,
so make sure to update it,
or you can just change the region of your realtime database to US region.