Why can React hooks be used conditionally with throw errors?

Viewed 1705

So we all know we can't put React hooks after or in conditionals as the documentation says.

function MyComponent(...) {
   if (condition) { 
      React.useState() // not allowed
   }
   return <div></div>;
}

function MyComponent(...) {
   if (condition) { 
      return null;
   }
   React.useState() // also not allowed
   return <div></div>;
}

With the eslint plugin for react hooks, we get build errors saying the above are not allowed.

But why does the plugin not respond to this

function MyComponent(...) {
   if (errorCondition) { 
      throw Error;
   }
   React.useState() // allowed???
   return <div></div>;
}

Is it that this isn't allowed and the plugin isn't updated to catch this? or is this actually allowed? The documentation doesn't seem to say anything on this

1 Answers

I think the more important question may be why would a component decide to throw an error like this versus issuing a side-effect to indicate an error has happened and simply return null.

As you've shown, conditional early return prohibits React hook usage.

function MyComponent(...) {
  if (condition) { 
    return null;
  }
  React.useState() // not allowed
  return <div></div>;
}

By throwing an error you are bailing out of the rest of the render, so whether or not a React hook is callable afterwards is a moot point.

function MyComponent(...) {
  if (errorCondition) { 
    throw Error;
  }
  React.useState() // allowed
  return <div></div>;
}

Consider this example:

function MyComponent(...) {
  try {
    if (condition) { 
      throw Error;
    }
    React.useState() // not allowed
  } catch {
    // caught
  }
  return <div></div>;
}

This will also yield a warning from the linter because you are again conditionally invoking a React hook.

Is it that this isn't allowed and the plugin isn't updated to catch this? or is this actually allowed?

I don't think it's disallowed, but as I stated above, flagging it seems unnecessary since simply throwing an error ceases to render the rest of the component. My guess is that the React team is indifferent about this as it would be extremely uncommon to throw an error like this and hope some parent component can handle this exception versus just handling it locally and returning null normally.

Related