React Native & Firebase : user info not being stored in database - javascript

I'm trying to create a new user and store their information in firebase database. I successfully create the user but the user information isn't getting stored in firebase.
The function that is running is handleAuthWithFirebase
The console.log("Storing user") is showing up in the console so I'm not sure why firebase.database().ref().set isn't running.
Here is my code
export function handleAuthWithFirebase (newUser) {
return function (dispatch, getState) {
dispatch(authenticating());
console.log(newUser);
console.log('Signing up user');
var email = newUser.email;
var password = newUser.password;
firebase.auth().createUserWithEmailAndPassword(email, password).catch(error => {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
}).then(() => {
const user = firebase.auth().currentUser;
// Set user in Firebase
console.log("Storing user")
firebase.database().ref('/users/' + user.uid).set({
name: newUser.displayName,
username: newUser.username,
email: newUser.email
})
}).then(() => {
const user = firebase.auth().currentUser;
dispatch(isAuthed(user.uid))
})
}
}

The problem is that you're missing a child object, so you have to specify it after ref. It would be more helpful if you can post the tree of your database as well, but before try this and figure out yout child.
firebase.database().ref('myRef').child('myChild').set({
name: newUser.displayName,
username: newUser.username,
email: newUser.email
})

Here's what I got working, for those coming across this post.
firebaseApp.auth()
.createUserAndRetrieveDataWithEmailAndPassword(this.state.email, this.state.password)
.then(response => {
firebaseApp.database().ref('users').child(response.user.uid).set({
firstName: this.state.firstName,
lastName: this.state.lastName,
username: this.state.username,
email: this.state.email
});
response.user.sendEmailVerification().then(response => {
AlertIOS.alert('Message', 'Sending email verification to '+this.state.email)
});
this.setState({authenticating: false})
}, error => {
AlertIOS.alert('Error', error.message);
this.setState({authenticating: false})
})

Related

FirebaseError: Expected type "'Zu'", but it was: a custom ea object

I keep getting the error above when trying to sign in with Google on Firebase. My code
const provider = new GoogleAuthProvider();
export const auth = getAuth();
export async function signUpGoogle(userType) {
return await signInWithPopup(auth, provider)
.then((result) => {
// This gives you a Google Access Token. You can use it to access the Google API.
const credential = GoogleAuthProvider.credentialFromResult(result);
const token = credential.accessToken;
// The signed-in user info.
const user = result.user;
// ...
// create user in firestore
//init services
// Add a new document in collection "users"
setDoc(collection(db, "users", "/", `${userType}`, '/', 'users'), {
userId: user.uid,
firstName: user.displayName,
lastName: user.displayName,
contactNumber: user.phoneNumber,
county: "",
idNumber: "",
city: "",
zipCode: "",
fullName: "",
email: user.email,
imageAsUrl: {
imageAsUrl: user.photoURL,
},
}).catch((e) => {
console.log(e.toString());
});
sessionStorage.setItem("Auth Token", token);
return true
}).catch((error) => {
// Handle Errors here.
const errorCode = error.code;
const errorMessage = error.message;
// The email of the user's account used.
const email = error.email;
// The AuthCredential type that was used.
const credential = GoogleAuthProvider.credentialFromError(error);
console.log(errorCode, errorMessage);
console.log(error);
// ...
return false
});
}
I have folowed the google documentation about signin with google and javascript
The error that i am getting is
FirebaseError: Expected type 'Zu', but it was: a custom ea object
The setDoc() takes a DocumentReference as a parameter i.e. you must specify the document ID. You can use addDoc() instead if you want to generate a random ID. But it might be useful to use user's UID as the document ID itself so try:
setDoc(doc(db, `users/${userType}/users/${user.uid}`), {
userId: user.uid,
firstName: user.displayName,
// ...
}).catch((e) => {
console.log(e.toString());
});

Trying to create a document whenever a user signs up

I am trying to create a document in firestore in the path "users" and the name user.uid every time a new user signs up. In this document I want to store some attributes such as firstname, lastname, email and uid. The issue i have is that the auth works perfectly, but no document is created.
var email = signupEmail.value;
var password = signupPassword.value;
var firstname = signupFirstname.value;
var lastname = signupLastname.value;
var password_repeat = signupRepeatPw.value;
const auth = getAuth();
const db = getFirestore();
if (firstname != "" && lastname != "") {
if (password == password_repeat) {
createUserWithEmailAndPassword(auth, email, password)
.then(async (userCredential) => {
const user = userCredential.user;
await setDoc(doc(db, "users", user.uid), {
firstName: firstname,
lastName: lastname,
accountLevel: 0,
UID: user.uid,
email: email,
})
.then(() => {
console.log("Document successfully written!");
})
.catch((error) => {
console.error("Error writing document: ", error);
});
})
.catch((error) => {
const errorCode = error.code;
var errorMessage = error.message;
Any help will be very appreciated as I have been stuck on this for quite some time!
Best regards,
Isak
If anyone else is struggling with this issue, I fixed my mistake.
The problem was that I redirected the user to their profile page when the auth state changed, from another script tag running simaltaniously. This led to the code redirecting the user before the promise was complete and therefore it does not update the db.
Best regards,
Isak

Can't add user to firestore database after signing up with firebase

I want to add a user to a firestore database after signing up through firebase with email and password. I get no errors, and the user is created and is visible in firebase auth. However the user is not added to the firestore database.
Does anyone know how to make this work? My code snippet is pasted below.
firebase.initializeApp(config);
const auth = firebase.auth();
const db = firebase.firestore();
auth.createUserWithEmailAndPassword(email, pass).then(cred => {
const userId = cred.user.uid;
const userData = {
firstName: firstName,
lastName: lastName,
email: email
};
db.collection("users").doc(userId).set(userData).then(() => {
console.log("User successfully added to the DB!");
})
.catch((e) => {
console.log("Error adding user to the DB: ", e);
});
}).then(() => {
console.log('User created! - ' + email);
}).catch(e => {
console.log(e.message);
txtErrMsg.classList.remove('hide');
txtErrMsg.innerHTML = e.message;
});
FYI: I have console logged the parameters (userId and userData), and they appear just fine.
Thanks!
I figured out what was wrong with my code.
I wrote another method auth.onAuthStateChanged() which was interfering with my action to write to the database. Since I have two auth files (signup.js and login.js), I decided to only keep this method in login.js and to remove it from signup.js.
Now I can successfully add the user to the DB upon signup (signup.js), and I don't need to add anything to the DB when a user is simply logging in (login.js).
I hope this helps anyone out there experiencing the same problem.
I experienced that problem myself. The only way I managed to get this working was to await auth first, and then add the user to firestore:
I have a firebaseConfig.js where I set up the usersCollection:
import firebase from 'firebase';
import 'firebase/firestore';
const firebaseConfig = {
apiKey: ......
};
firebase.initializeApp(firebaseConfig);
const auth = firebase.auth();
const db = firebase.firestore();
const usersCollection = db.collection('users');
export { auth, usersCollection };
Then, I use it like this.
const fb = require('../firebaseConfig.js');
....
const cred = await fb.auth
.createUserWithEmailAndPassword(
'someemail#test.com',
'password123'
)
.catch(e => {
console.log(e.message);
});
if (cred) {
console.log({ cred });
const userId = cred.user.uid;
const userData = {
firstName: 'firstName',
lastName: 'lastName',
email: 'email',
};
fb.usersCollection
.doc(userId)
.set(userData)
.then(() => {
console.log('User successfully added to the DB!');
})
.then(() => {
console.log('User created!);
})
.catch(e => {
console.log('Error adding user to the DB: ', e);
});
}
When I ran this code I got the following in my log:
And it appears in my database like this:

Problem creating document within subcollection

I'm working on a signup form. User registers, then in Firebase in the "companies" collection I add a new company, then a "users" collection is added under the just-created company, and the just-created user is added as a document to the company.
Everything is working fine until my code tries to add a new collection "users" under the just created company. Here's my code thus far:
return async (dispatch, getState) => {
try {
const { companyName, email, password } = getState().user;
const response = await Firebase.auth().createUserWithEmailAndPassword(
email,
password
);
if (response.user.uid) {
// Set up company
const company = {
name: companyName,
owner: response.user.uid
};
// Create company
db.collection("companies")
.add(company)
.then(ref => {
console.log("Company ID ", ref.id);
console.log("User ID ", response.user.uid);
// Set up first user
const user = {
uid: response.user.uid,
email: email
};
// Add first User
db.doc(ref.id)
.collection("users")
.add(user);
});
dispatch({ type: SIGNUP, payload: user });
}
} catch (e) {
alert(e);
}
};
Those console.logs return the correct IDs, So it looks like there's an issue with how my reference to the just-created company is being created? How would I fix that?
db.doc(ref.id).collection("users").add(user) may be wrong.
Could you try ref.collection("users").add(user) or db.collection("companies").doc(ref.id).collection("users").add(user);
// Add first User
// db.doc(ref.id)
// .collection("users")
// .add(user);
ref.collection("users").add(user);
// db.collection("companies").doc(ref.id).collection("users").add(user);
See:
https://firebase.google.com/docs/reference/js/firebase.firestore.CollectionReference#add
https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentReference#collection
https://firebase.google.com/docs/reference/js/firebase.firestore.Firestore#doc
In addition to zkohi's correct answer, note that you are mixing the use of async/await with then(), which is not recommended. The following should do the trick (untested):
return async (dispatch, getState) => {
try {
const { companyName, email, password } = getState().user;
const response = await Firebase.auth().createUserWithEmailAndPassword(
email,
password
);
if (response.user.uid) {
// Set up company
const company = {
name: companyName,
owner: response.user.uid,
};
// Create company
const compRef = await db.collection('companies').add(company);
console.log('Company ID ', compRef.id);
const user = {
uid: response.user.uid,
email: email,
};
await compRef.collection('users').add(user);
dispatch({ type: SIGNUP, payload: user });
}
} catch (e) {
alert(e);
}
};
Note how we define the users subcollection:
compRef.collection('users').add(user);
just by calling the collection() method on the company's DocumentReference. This last point is in line with zkohi's answer.

Update Firebase User's email and password after loginWithCustomToken on node.js

My use case is similar to Parse Suggested Migration Strategy
(but I'm not using Parse, just integrating 3rd party auth)
On Node.js / express, here is relevant code:
firebaseWebSDK.auth().signInWithCustomToken(customToken)
.then(user => {
let nextStep
let message
// check if returned user has "email" field set..
if (!user.email) {
message = 'Signed up user, saved: email, password, and display name.'
const usersRef = firebaseServerSDK.database().ref('users')
nextStep = Promise.all([
user.updateEmail(email),
user.updatePassword(password),
user.updateProfile({ displayName }),
usersRef.child(user.uid).set({ displayName, email }),
])
} else {
message = `User already exists for that email: ${email}`
nextStep = Promise.resolve(null)
}
nextStep.then(() => {
delete req.session.user
return res.json({ message })
})
.catch(updateError => res.json({ error: updateError.message }))
})
.catch(signInError => {
const errorCode = signInError.code
const errorMessage = signInError.message
return res.json({ type: 'signInError', errorCode, errorMessage })
})
Here's what happens:
Sometimes user email updates, sometimes it doesn't
Never does the password update
Pretty sure the Profile updates always
database "/users" saves correctly, no issues there.
Always tested with new user, so it's always entering the "update" branch of code...
Any ideas? Code follows structure of documentation linked above, so not sure what issue is.

Categories