-
Notifications
You must be signed in to change notification settings - Fork 7.7k
Warning page for invalid Hook calls #1613
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
383f8a3
add warning for invalid hook call
gaearon 25b51be
Fix versions
gaearon d0decb9
Split code examples
gaearon 7b0ac05
unnecessary comma
gaearon 5a0d715
tweaks
gaearon 532a300
Update content/warnings/invalid-hook-call-warning.md
93446b6
nit
gaearon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,121 @@ | ||||||
--- | ||||||
title: Invalid Hook Call Warning | ||||||
layout: single | ||||||
permalink: warnings/invalid-hook-call-warning.html | ||||||
--- | ||||||
|
||||||
You are probably here because you got the following error message: | ||||||
|
||||||
> Hooks can only be called inside the body of a function component. | ||||||
|
||||||
There are three common reasons you might be seeing it: | ||||||
|
||||||
1. You might have **mismatching versions** of React and React DOM. | ||||||
2. You might be **breaking the [Rules of Hooks](/docs/hooks-rules.html)**. | ||||||
3. You might have **more than one copy of React** in the same app. | ||||||
|
||||||
Let's look at each of these cases. | ||||||
|
||||||
## Mismatching Versions of React and React DOM | ||||||
|
||||||
You might be using a version of `react-dom` (<= 16.8.0) or `react-native` (<= 0.60) that doesn't yet support Hooks. You can run `npm ls react-dom` or `npm ls react-native` in your application folder to check which version you're using. If you find more than one of them, this might also create problems (more on that below). | ||||||
|
||||||
## Breaking the Rules of Hooks | ||||||
|
||||||
You can only call Hooks **while React is rendering a function component**: | ||||||
|
||||||
* ✅ Call them at the top level in the body of a function component. | ||||||
* ✅ Call them at the top level in the body of a [custom Hook](/docs/hooks-custom.html). | ||||||
|
||||||
**Learn more about this in the [Rules of Hooks](/docs/hooks-rules.html).** | ||||||
|
||||||
To avoid confusion, it’s **not** supported to call Hooks in other cases: | ||||||
|
||||||
* 🔴 Do not call Hooks in class components. | ||||||
* 🔴 Do not call in event handlers. | ||||||
* 🔴 Do not call Hooks inside functions passed to `useMemo`, `useReducer`, or `useEffect`. | ||||||
|
||||||
If you break these rules, you might see this error. | ||||||
|
||||||
```js{2-3,8-9,15-16,23-24,33-34} | ||||||
function Counter() { | ||||||
// ✅ Good: top-level in a function component | ||||||
const [count, setCount] = useState(0); | ||||||
// ... | ||||||
} | ||||||
|
||||||
function useWindowWidth() { | ||||||
// ✅ Good: top-level in a custom Hook | ||||||
const [width, setWidth] = useState(window.innerWidth); | ||||||
// ... | ||||||
} | ||||||
|
||||||
function Bad1() { | ||||||
function handleClick() { | ||||||
// 🔴 Bad: inside an event handler (to fix, move it outside!) | ||||||
const theme = useContext(ThemeContext); | ||||||
} | ||||||
// ... | ||||||
} | ||||||
|
||||||
function Bad2() { | ||||||
const style = useMemo(() => { | ||||||
// 🔴 Bad: inside useMemo (to fix, move it outside!) | ||||||
const theme = useContext(ThemeContext); | ||||||
return createStyle(theme); | ||||||
}); | ||||||
// ... | ||||||
} | ||||||
|
||||||
|
||||||
class Bad3 extends React.Component { | ||||||
render() { | ||||||
// 🔴 Bad: inside a class component | ||||||
useEffect(() => {}) | ||||||
// ... | ||||||
} | ||||||
} | ||||||
``` | ||||||
|
||||||
You can use the [`eslint-plugin-react-hooks` plugin](https://www.npmjs.com/package/eslint-plugin-react-hooks) to catch some of these mistakes. | ||||||
|
||||||
>Note | ||||||
> | ||||||
>[Custom Hooks](/docs/hooks-custom.html) *may* call other Hooks (that's their whole purpose). This works because custom Hooks are also supposed to only be called while a function component is rendering. | ||||||
|
||||||
|
||||||
## Duplicate React | ||||||
|
||||||
In order for Hooks to work, `react` import from your application code needs to resolve to the same module as the `react` import from inside the `react-dom` package. | ||||||
|
||||||
If these `react` imports resolve to two different exports objects, you will see this warning. This may happen if you **accidentally end up with two copies** of the `react` package. | ||||||
|
||||||
If you use Node for package management, you can run this check in your project folder: | ||||||
|
||||||
npm ls react | ||||||
|
||||||
If you see more than one React, you'll need to figure out why this happens, and fix your dependency tree. For example, maybe a library you're using incorrectly specifies `react` as a dependency (rather than a peer dependency). Until such a library is fixed, [Yarn resolutions](https://yarnpkg.com/lang/en/docs/selective-version-resolutions/) is one possible workaround. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
You can also try to debug this problem by adding some logs and restarting your development server: | ||||||
|
||||||
```js | ||||||
// Add this in node_modules/react-dom/index.js | ||||||
window.React1 = require('react'); | ||||||
|
||||||
// Add this in your component file | ||||||
require('react-dom'); | ||||||
window.React2 = require('react'); | ||||||
console.log(window.React1 === window.React2); | ||||||
``` | ||||||
|
||||||
If it prints `false` then you might have two Reacts and need to figure out why that happened. [This issue](https://github.com/facebook/react/issues/13991) includes some common reasons encountered by the community. | ||||||
|
||||||
This problem can also come up when you use `npm link` or an equivalent. In that case, your bundler might "see" two Reacts — one in application folder and one in your library folder. Assuming `myapp` and `mylib` are sibling folders, one possible fix is to run `npm link ../myapp/node_modules/react` from `mylib`. This should make the library use the application's React copy. | ||||||
|
||||||
>Note | ||||||
> | ||||||
>In general, React supports using multiple independent copies on one page (for example, if an app and a third-party widget both use it). It only breaks if you call `ReactDOM.render()` for a component with a different `require('react')` than seen by `react-dom`. | ||||||
|
||||||
## Other Causes | ||||||
|
||||||
If none of this worked, please comment in [this issue](https://github.com/facebook/react/issues/13991) and we'll try to help. Try to create a small reproducing example — you might discover the problem as you're doing it. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.