felix_xiao
felix_xiao

Reputation: 1628

Firebase Authentication and State Issue

I am a student learning React. I am trying to create a web app where a user must sign in with Google before viewing any of the content. I began with the code from the github-notetaker example and have edited Main.js. So far, I am writing the entire logic inside the init() method and setting loggedIn and email values in this.state.

import React from 'react';
import { RouteHandler } from 'react-router';
import Rebase from 're-base';

class Main extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      loggedIn: props.loggedIn,
      email: props.email
    };
  }

  authDataCallback(authData) {
    if (authData) {
      console.log('User is already logged in.');
      console.log(authData["google"]["email"]); // works as expected
      this.setState({
        loggedIn: true,
        email: authData["google"]["email"]
      });
      console.log(this.state.email); // does not work as expected
    } else {

      this.setState({
        loggedIn: false
      });
      console.log('Attempting to authenticate user account');
      this.ref.authWithOAuthPopup('google', function (error, authData) {
        if (error) {
          console.log('Login Failed!', error);
        } else {
          console.log('Authenticated successfully');
        }
      }, {
        scope: "email"
      });
    }
  }
  init(){
    console.log('Init called');
    this.ref = new Firebase('https://myapp.firebaseio.com/');
    this.ref.onAuth(this.authDataCallback.bind(this));
  }

  componentWillMount(){
      this.router = this.context.router;
  }
  componentDidMount(){
    this.init();
  }
  componentWillReceiveProps(){
    this.init();
  }
  render(){
    if (!this.state.loggedIn) {
      return (
        <div className="main-container">
          <div className="container">
            <h3>You are not authenticated. <a href="">Login</a></h3>
          </div>
        </div>
      )
    } else {
      return (
        <div className="main-container">
          <div className="container">
            <RouteHandler {...this.props}/>
          </div>
        </div>
      )
    }
  }
};
Main.propTypes = {
  loggedIn: React.PropTypes.bool,
  email: React.PropTypes.string
};
Main.defaultProps = {
  loggedIn: false,
  email: ''
}
Main.contextTypes = {
  router: React.PropTypes.func.isRequired
};
export default Main;

I am encountering an odd bug and believe that I am doing this the wrong way. When the user authenticates successfully, all of the information is saved and the user's email is written. Here's what the console log looks like: User is already logged in. [email protected] // corresponds to authData["google"]["email"] [email protected] // corresponds to this.state.email = CORRECT!!

However, when I refresh the page, the new print looks like this, and it appears that the email and object are still available to me but are not getting saved in this.state. User is already logged in. [email protected] // corresponds to authData["google"]["email"] null

I am currently learning React and so this may be a really simple error. Thank you so much for your time and help in advance. If you could point me in the right direction or let me a know a better way to do this, I'd really appreciate it. Thanks!

Upvotes: 0

Views: 570

Answers (2)

felix_xiao
felix_xiao

Reputation: 1628

I believe I found the reason for my issue. When I call the following code in render()

<h1> {this.state.email} </h1>

It works just fine. Therefore, my conclusion is that console.log(this.state.email) is somehow run before this.setState() is fully completed.

Upvotes: 1

andreasonny83
andreasonny83

Reputation: 1211

You're writing the code wrong. var currentAuthData = this.ref.getAuth(); sends a request to fireBase to get the authentication, however the next line of code if (currentAuthData) { is run before fireBase can retrieve the correct information. You must use a callback function instead.

ref.onAuth(authDataCallback);

function authDataCallback(authData) {
  if (authData) {
    console.log('User is already logged in.');
  }
}

Upvotes: 0

Related Questions