React native: why doesn't my catch statement catch the error which I get?

I am trying to save some data in firestore and purposefully I introduced an error, so I can see if I handle error messages correctly. That is, I know where the error is, and I know why I am getting it. The problem is that I don't go into the catch statement and I don't know why:

const saveBio = async () => {
   setSaving(true);
    await firebase
      .firestore()
      .collection("collection")
      .doc(firebase.auth().currentUser.uid)
      .set(
        {
          bio: bio,
        }
      )
      .then(() => {
        console.log("managed to save bio");
      })
      .catch((error) => {
        //I expect to go here, but for some reason I don't
        console.log("Some error when saving bio: ", error);
        setError(true);
      });
    setSaving(false);
  };

The error which I am seeing on the console is the following: [Unhandled promise rejection: ReferenceError: Can't find variable: bio] Again, the error is expected, but I would expect to go inside my catch case and to see my console.log. How should I handle these types of error cases?


Solution 1:

Function arguments are evaluated before functions are called. You could look at this:

await someFn()
  .set(
    {
      bio: bio,
    }
  )
  .then(() => {
    console.log("managed to save bio");
  })
  .catch((error) => {

as

const paramToPassToSet = { bio: bio };
await someFn()
  .set(paramToPassToSet)
  .then(() => {
    console.log("managed to save bio");
  })
  .catch((error) => {

The Promise chain doesn't get initialized in the first place, because an error was thrown during the evaluation of the arguments.

This is a very strange error to have, though - for reasonable code, identifiers (other than possible globals) should always be defined.

If you run into this sort of problem often, consider using an IDE or a linter that will warn you about this sort of thing. ESLint's no-undef would have shown you the problem. (For any reasonably serious code, I'd consider using a linter essential - it can turn runtime errors into trivially-fixable compile-time errors. TypeScript helps too, but it has a higher learning curve than a linter.)