Jon Nicholson
Jon Nicholson

Reputation: 1131

Attempting to render Firebase Auth details returning 'undefined' in React web app

I'm attempting to render a user's displayName and email upon loading a 'profile page' from what is stored in my Firebase Auth.

I'm doing this within a 'componentDidMount' by setting the state respective to the response from Firebase.

Strangely though, the response is 'undefined' when the page loads, and whenever you refresh it. However, if I change the code in any way, save then reload, the data pulls through and renders in my inputs as desired.

An example of this happening is if I add a 'console log' to my code, save then refresh - the data will start rendering, and it'll also log instead of returning 'undefined'.

I'm not totally sure what I'm doing wrong, I've attempted to add a async/await to my componentDidMount, to no avail.

Here's my component:

class Profile extends Component {
  constructor(props) {
    super(props);

    this.state = {
      displayName: "",
      email: "",
    };
  }

  async componentDidMount() {
    var user = await firebase.auth().currentUser;
    var name, email;

    if (user != null) {
      if (user.displayName !== "") {
        name = user.displayName;
      } else {
        name = "";
      }

      if (user.email !== "") {
        email = user.email;
      } else {
        name = "";
      }
    }

    console.log(name);
    console.log(email);

    return this.setState({
      displayName: name,
      email: email,
    });
  }

  onChange = (e) => {
    this.setState({ [e.target.name]: e.target.value });
  };

  render() {
    return (
      <div>
        <input
          className="profile-info-type"
          type="text"
          name="displayName"
          value={this.state.displayName || ""}
          onChange={this.onChange}
        />

        <input
          className="profile-info-type"
          type="email"
          name="email"
          value={this.state.email || ""}
          onChange={this.onChange}
        />
      </div>
    );
  }
}

Any feedback would be appreciated.

EDIT: Updated componentDidMount call:

 componentDidMount() {

    firebase.auth().onAuthStateChanged(function(user) {
    if (!user) {
      this.setState({
        displayName: "",
        email: ""
      })
    } else {
        this.setState({
          displayName: user.displayName,
          email: user.email
        })
    }
  });

  }

Upvotes: 0

Views: 594

Answers (1)

Doug Stevenson
Doug Stevenson

Reputation: 317467

Firstly, firebase.auth().currentUser is not asynchronous, so using await is not helpful here. It will not wait for the current user object to become available. In fact, currentUser is initially null when a page first loads. The object will not be available until some time later, after Firebase Auth has determined that the current user object is valid.

To find out when the user object is first available, you shouldn't use currentUser at all. You should instead use an auth state observer to receive a callback when the user's auth state changes:

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
  } else {
    // User is signed out.
  }
});

You will need to arrange for a call to setState when this happens, so you can update your UI.

I also recommend reading more about why currentUser is unexpcetedly null.

Upvotes: 2

Related Questions