Search code examples
javascriptangularfirebasefirebase-authenticationangularfire

Update Profile During SignUp Angular Firebase


I am using angularfire/firebase for an Angular project where I am working through authentication.

When a user signs up, the following function is called:

  signup(email: string, password: string, name: string) {
    return this.fireAuth
      .createUserWithEmailAndPassword(email, password)
      .then((res) => {
        res.user?.updateProfile({
          displayName: name,
        });

        // set vars and local storage
      });
  }

In my app.component, I have the following subscription to track changes and store in my state management (I don't think StateMgmt is the issue here):

ngOnInit() {
  this.fireAuth.authState.user.subscribe((res) => {
  if(res) {
    console.log(res);
    console.log(res.displayName);
    this.store.dispatch(new SetUser(res));
  }
}

When a user signs up, the name they enter upon signup is set through the res.user.updateProfile(... function, and since the authState had a change, the subscription in the app.component prints out an object and stores to the SetUser(res) state.

The console.log() from here in the app state prints out a large object, including the email, uid, and displayName. This is then stored in my state object. However, on theconsole.log(res.displayName), the result is null until I refresh the page triggering an "auto logon" where the displayName is fetched from firebase.

It seems to me the object of the .then((res)... from my signUp() updateProfile is not being triggered until after the user is already changed and stored.

Is there a way to make this signUp function work so that the SetUser(res) is only dispatched once the updateProfile({... is complete and the displayName is no longer null?

From my app.component console.log(res):

{
 "uid": "vbn6TA8vTiLi7J2",
 "displayName": "my name",
 "photoURL": null,
 "email": "email@email.com",
 ...
}

app.component console.log(res.displayName): null

EDIT

Another interesting thing I found is that when I take a copy of the res and print it out, the displayName is also null.

 const r = JSON.parse(JSON.stringify(res));
 console.log(res);
 console.log(r);

the console.log(r) has an object where the displayName is null. The console.log(res) has an object where the displayName is NOT null and is the name passed in to the signUp(... function.


Solution

  • Even waiting for the user to be finalized via async await before moving on did not work.

    What I ended up doing was the following:

    In my signUp() function, once the user was created, I retrieved the current use via this.fireAuth.authState (fireAuth is from AngularFireAuth in my constructor). I subscribed to this, while piping to only take the first value, and then dispatched my SetUser function. This ensures that the function is only running after the updateProfile is complete using a .then().

    Because I moved the state dispatch into my signup function, I removed the subscription from my AppComponent.

    Here is my signup function from the auth service:

    ...
    
      constructor(
        public fireAuth: AngularFireAuth,
      ) {
        this.user = this.fireAuth.authState;
      }
    
      signup(email: string, password: string, name: string) {
        return this.fireAuth
          .createUserWithEmailAndPassword(email, password)
          .then((res) => {
            res.user
              ?.updateProfile({
                displayName: name,
              })
              .then(() => {
                this.user.pipe(first()).subscribe((res) => {
                  this.store.dispatch(new SetUser(res));
                });
              });
          });
      }