0

I have two files, an App.js where I set up my React Navigation StackNavigator along with my firebase instance and a Login.js where I login users.

I am trying to detect if a user has already logged in (thru firebase persistent login) but for some reason, my firebase instance is not being detected in Login.js's componentDidMount(). This doesn't make sense to me because elsewhere in my Login.js, I call fxns on my firebase instance, like logging in with Google.

How should I arrange the firebase initialization/auth check to ensure the firebase instance is detected correctly along with the persistent auth check?

I have already looked at this question but that person seems to have a different problem as they are only concerned with the firebase instance in a single file.

Relevant portions of App.js

import { StackNavigator } from 'react-navigation';
import * as firebase from 'firebase';
import 'firebase/firestore';
import Login from './components/login';

const Application = StackNavigator({
    Login: { screen: Login,
        navigationOptions: {
                title: 'Login',
        }
    },
    SignUp: { screen: SignUp,
        navigationOptions: {
           title: 'Signup',
         }
    },
    Home: { screen: Home,
        navigationOptions: {
           title: 'Home'
       }
    },
});

const firebaseConfig = {
    apiKey: "APIKEY",
    authDomain: "AUTH_DOMAIN",
    databaseURL: "DATABASE_URL",
    projectId: "PROJECT_ID",
    storageBucket: "BUCKET",
}

export default class App extends React.Component {
    componentDidMount(){
        //if no instance exists, initialize one
        if (!firebase.apps.length) {
            firebase.initializeApp(firebaseConfig);
        }
    }
    render() {
        return (
            <Application/>
        );
    }
}

Relevant portion of Login.js

import * as firebase from 'firebase';
import Home from './home';

export default class Login extends React.Component {

    constructor(props){
        super(props)
        this.state = {
            isLoggingIn: true,
            authFlag: false,
        }
    }

    componentDidMount() {
        //error is on the following line
        firebase.auth().onAuthStateChanged((user) => {
            if(!this.state.authFlag){
                this.setState({ authFlag: true })
                //persistent success, take user to Home
                if(user){
                     this.props.navigation.navigate('Home');
                     return;
                }

                //user hasn't logged in before, must log in
                else{
                     this.setState({isLoggingIn: false});
                     return;
                }
            }
        });
    }
}
David Owens
  • 645
  • 6
  • 25
  • 2
    Child components mount before their parents. `componentDidMount` of your login component is happening before `componentDidMount` of your app..... https://stackoverflow.com/questions/32814970/is-componentdidmount-of-parent-called-after-all-componentdidmount-of-children – Max Baldwin May 03 '18 at 21:42
  • I see. I'm having trouble understanding how this is compatible with the parent->child flow of data in React-Native. If a child's component is mounted before that of it's parent, is that not denying data initialized in a parent component the ability to flow to its child (as in my case)? – David Owens May 03 '18 at 21:46
  • It depends on how you get your data. If you are fetching your data in `componentDidMount` then you should do it in the parent. Then the parent can trickle down the data to its children and the children would receive the data in `componentWillReceiveProps`. At least until React 17 that is... – Max Baldwin May 03 '18 at 21:54
  • Say there is a Navigator with `App.js` -> `Login.js` -> `Home.js`, this means that one would initialize their firebase instance in `Home.js`?? How would one refactor the code I have posted to initialize it in `App.js` and allow `Login.js`'s `componentDidMount()` to access it? – David Owens May 03 '18 at 22:04

1 Answers1

1

As I mentioned in my comments above child components mount before their parents. componentDidMount of your login component is happening before componentDidMount of your app. Stack overflow question outlining the deets.

Just doing a quick search, it looks like most people do firebase.initializeApp outside of their component. Was just reading this.

Max Baldwin
  • 3,404
  • 3
  • 26
  • 40