Flama
Flama

Reputation: 868

React Native: Unable to catch thrown error

I'm trying to catch an error from my signIn method and then display an alert in my code. I get a warning saying "Unhandled promise rejection..."

export default function Login({navigation}){
    
    
    const [email, setEmail]  = React.useState('');
    const [password, setPassword] = React.useState('');
    const [showAlert, setShowAlert] = React.useState(false);
    const [showAlert2, setShowAlert2] = React.useState(false);
    const { signIn } = React.useContext(AuthContext);

    const submit = async() => {

        if (email === '' || password === '') {
            setShowAlert(true);
        } else {
            signIn(email, password).catch(error => 
                setShowAlert2(true)); // THIS NEVER GETS TRIGGERED, WHY?
        }
        
    }

    ...
}

signIn is defined in my App.js like this:

const authContext = React.useMemo(() => {
    return {
      signIn: (email, password) => {
          auth().signInWithEmailAndPassword(email.email, password.password)
          .then((res) => {
            setIsLoading(false);
            setUser(res.user.uid);
          })
          .catch(error => {
            throw error; // This is the error that should be catched in "submit"
          })
      },
      signUp: () => {
        setIsLoading(false);
        setUser("test");
      },
      signOut: () => {
        setIsLoading(false);
        auth().signOut().then(() => console.log('User signed out!'));
        setUser(null);
      }
    };
}, []);

As you see I perform "throw error" at some point. That is the error I want to catch in my submit const above.

This is the error I get:

TypeError: undefined is not an object (evaluating 'signIn(email, password).catch')

Upvotes: 3

Views: 904

Answers (1)

Flagship1442
Flagship1442

Reputation: 1726

You need to return that auth() call, and then remove the catch, then the error will be passed to whatever calls signIn

    signIn: (email, password) => {
      return auth() // add return here
        .signInWithEmailAndPassword(email.email, password.password)
        .then(res => {
          setIsLoading(false);
          setUser(res.user.uid);
        })
    },

You can even clean this up further by removing the curly braces and return. The arrow will return the next value automatically:

  signIn: (email, password) =>
    auth()
      .signInWithEmailAndPassword(email.email, password.password)
      .then(res => {
        setIsLoading(false);
        setUser(res.user.uid);
      });

The error you're seeing is basically saying that it can't find a catch method on the returned value of signIn. This is true because in your version signIn does not return anything. The signIn function must return a promise (which is just an object with methods like then and catch); if you return a promise then it will have that catch method, that can then be called.

Upvotes: 4

Related Questions