
How to Fix Invalid Hook Call Warning in React
React Hooks (like useState and useEffect) revolutionized state management in frontend applications. However, if you violate their strict execution rules, React will throw a fatal error that crashes your app:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same appThis error is unique because it can be caused by either bad code syntax or corrupted node_modules environments.
In this guide, we will analyze these three common causes, inspect hook calls, and resolve dependency conflicts.
Cause 1: Breaking the Rules of Hooks
React hooks rely on a stable, index-based call order. On every render, React executes hooks in the exact same sequence. If you disrupt this order, React's internal state tracker breaks.
Scenario A: Calling Hooks Conditionally or in Loops
If you wrap a hook inside an if statement or a loop, it might not execute on every render:
// AVOID: Conditional hook call
if (isLoggedIn) {
useEffect(() => {
fetchUserData();
}, []);
}- The Fix: Move the conditional checks inside the hook rather than wrapping the hook in the condition:
// Good: Hook runs unconditionally, condition is handled internally
useEffect(() => {
if (isLoggedIn) {
fetchUserData();
}
}, [isLoggedIn]);Scenario B: Calling Hooks inside Normal JavaScript Functions
You cannot invoke a hook inside a utility function or event handler:
// AVOID: Calling hook inside a helper function
function formatUser(user) {
const [name, setName] = useState(user.name); // Crashes!
return name.toUpperCase();
}- The Fix: Restructure the helper into a Custom Hook. In React, any function starting with
usecan contain other hooks safely:
// Good: Extracted into a Custom Hook starting with 'use'
function useFormatedUser(user) {
const [name, setName] = useState(user.name);
return name.toUpperCase();
}Cause 2: Multiple Copies of React in the Same Project
If your code syntax is clean but you still get the "Invalid hook call" error, your local build system is likely loading two different instances of the React library.
This frequently occurs when building component libraries, working in monorepos (using Lerna, Turbo, or pnpm workspaces), or linking local packages using npm link / pnpm link.
If your application loads:
- One copy of React from
my-app/node_modules/react - A second copy of React from
my-library/node_modules/react
The state synchronization between React DOM and React breaks, triggering the error.
Step 1: Detect Duplicate Copies
Run the dependency tree list command in your project root:
# Check how many copies of react are resolved
npm ls react
# For pnpm projects:
pnpm why reactIf your terminal output lists multiple versions of React resolved in different folders, you have duplicate copies.
Step 2: Configure Peer Dependencies (For Libraries)
If you are developing a component library, never declare React in the dependencies list of your library's package.json. Instead, declare it as a peerDependency:
// Inside your-library/package.json
{
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0"
}
}This instructs the compiler to reuse the host application's React library instance rather than installing a duplicate copy.
Step 3: Resolve Duplicates in pnpm/npm
You can force your package manager to resolve a single, project-wide version of React using the override configurations:
- For pnpm (
package.json):
"pnpm": {
"overrides": {
"react": "$react"
}
}- For npm (
package.json):
"overrides": {
"react": "^18.3.0"
}Run pnpm install or npm install after editing the overrides block to clean the dependency tree.
Conclusion
The "Invalid hook call" error indicates either a syntax violation or a duplicate library resolution issue. To fix it, ensure hooks are called unconditionally at the top level of React function components or custom hooks, verify that event handlers do not call hooks directly, and configure package manager overrides to eliminate duplicate React instances in linked or monorepo workspaces.