reactjs / reactjs/react.dev

[Suggestion]: Document that hooks can be called after a conditional `throw`

Open
#7,291 0 comments 10 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

type: documentation
Dominant language
JavaScript
Stars
11.8k
Forks
7.9k
Avg merge
1d 11h
Merged PRs (30d)
11

Description

Summary

I don't believe it is documented anywhere that calling a hook after a conditional throw statement is not a violation of the rules of hooks. If this is a valid pattern, it should be documented. If it is not, the Eslint rule rules-of-hooks should warn for it.

Page

Rules of hooks

Details

I realised this is effectively the pattern when using Next.js app router notFound(), which throws an Error in the component render. I had assumed this not being flagged by the rules-of-hooks was a limitation of the Next.js eslint plugin, but actually, this is not flagged as an issue with a standard throw:

const Component = ({ someOtherCondition }) => {
  const [foo, setFoo] = useState();

  if (someOtherCondition) throw new Error();

  const [bar, setBar] = useState();

  return (<>...</>);
};

My assumption is this is a valid pattern as if someOtherCondition becomes true, the error will be thrown up the call stack to the nearest error boundary, and the render that was in-progress will be discarded. There is not a case to have this conditional throw call more hooks than the previous render, only less. The rules of hooks state:

It’s not supported to call Hooks (functions starting with use) in any other cases, for example:

🔴 Do not call Hooks inside conditions or loops.
🔴 Do not call Hooks after a conditional return statement.

In the example above, the second useState call comes after a conditional throw statement. Not quite either of the cases in documentation.

If this is a valid pattern, it should be mentioned in the docs, with potential warnings about it not being a recommended workaround to conditionally call hooks (as there is no way to resume execution of the other path of the conditional once an error is thrown from the component).

If this isn't a valid pattern, it should be flagged by the eslint rule.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Rules of Hooks page and the documented rules-of-hooks behavior described in the issue. Reproduce the conditional throw example, then determine whether the page needs clarification or whether the ESLint rule should change; done means the behavior and its intended guidance are resolved and reflected in the appropriate place.

Written by the indexing model from the issue text.

Assessment

Tech stack
eslint, javascript, next.js, react
Domain
documentation
Issue type
Documentation
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.