React Navigation not working with Firebase in React Native App

Viewed 576

I have a funny problem.

When I press sign-up button, the function below is called in SignUp component.

//SignUp.js
signUpHandler = () => {
        if (this.state.email == '' || this.state.password == '') {
            alert("Email or Password is empty.")
        }
        else {
            firebase.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
                .then(() => this.props.navigation.navigate('ExtendedRegisteration'))
                .catch(error => { alert(error.message) });
        }
    }

Now this doesn't navigate to "ExtendedRegisteration" but when I do the below, it navigates just fine.

//SignUp.js
signUpHandler = () => {
        if (this.state.email == '' || this.state.password == '') {
            alert("Email or Password is empty.")
        }
        else {
                this.props.navigation.navigate('ExtendedRegisteration')
        }
    }

Is this a problem with Firebase? I need to navigate to "ExtendedRegisteration" after I signup using firebase.

Output from this.props in signUpHandler :

Object {
  "navigation": Object {
    "addListener": [Function addListener],
    "canGoBack": [Function canGoBack],
    "dangerouslyGetParent": [Function dangerouslyGetParent],
    "dangerouslyGetState": [Function anonymous],
    "dispatch": [Function dispatch],
    "goBack": [Function anonymous],
    "isFocused": [Function isFocused],
    "jumpTo": [Function anonymous],
    "navigate": [Function anonymous],
    "pop": [Function anonymous],
    "popToTop": [Function anonymous],
    "push": [Function anonymous],
    "removeListener": [Function removeListener],
    "replace": [Function anonymous],
    "reset": [Function anonymous],
    "setOptions": [Function setOptions],
    "setParams": [Function anonymous],
  },
  "route": Object {
    "key": "Sign Up-q-zIoH0VCp",
    "name": "Sign Up",
    "params": undefined,
  },
}
4 Answers

This isn't a problem with Firebase. The issue you are having is with accessing the navigation reference from within an arrow function that is executed after the promise returns. The scope of this is different from within that arrow function.

To get around situations like this React Navigation has a solution where you can define a function to call navigate directly.

import { createNavigationContainerRef } from '@react-navigation/native';

export const navigationRef = createNavigationContainerRef()

export function navigate(name, params) {
  if (navigationRef.isReady()) {
    navigationRef.navigate(name, params);
  }
}  

Then you can simply import navigate and use it like so.

navigate('ExtendedRegisteration');

The reason this isn't commonly used everywhere is because it can become problematic when you have complex nested routes, and it also doesn't give you access to other navigation methods, but for situations like yours it works fine.

'this' means context and it is most funny thing in react. Try console.log(this.props) to check whether the props in firebase then is same as the other example. Since the this was called from inside the promise it could have change the 'this' context. It happens more than expected times.

You could try creating a function

constructor(props){
    super(props);
    this._onUserCreation = this._onUserCreation.bind(this);
}

_onUserCreation=()=>{this.props.navigation.navigate('ExtendedRegisteration')};

//SignUp.js
signUpHandler = () => {
        if (this.state.email == '' || this.state.password == '') {
            alert("Email or Password is empty.")
        }
        else {
            firebase.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
                .then(() => this._onUserCreation())
                .catch(error => { alert(error.message) });
        }
    }

Pass this as a parameter from wherever you invoke the signup function and use that parameter in place of this.

Make sure you unmount FirebaseRecaptcha.FirebaseRecaptchaVerifierModal before you navigate

Related