Tutorials Logic, IN info@tutorialslogic.com

Invalid hook call warning in React Fix

What is This Error?

A strong invalid hook call note must separate rule-of-hooks mistakes from dependency problems. The warning can come from code structure, such as calling useState in a normal function, or from package structure, such as two React copies being loaded.

Debugging should move in two passes: first inspect the component code for hook placement, then inspect node_modules and package versions for duplicate React or mismatched react/react-dom.

The "Invalid hook call" warning occurs when React Hooks are called in an invalid context. This typically happens due to mismatched React versions, duplicate React installations, calling Hooks outside React components, or breaking the Rules of Hooks.

Common Causes

  • Mismatched versions of React and React DOM
  • Multiple copies of React in node_modules (duplicate React)
  • Calling Hooks in regular JavaScript functions (not React components)
  • Calling Hooks in class components
  • Breaking the Rules of Hooks (conditional calls, loops, etc.)

Quick Fix (TL;DR)

Immediate Fix: Check for duplicate React

Immediate Fix: Check for duplicate React
# Check for duplicate React
npm ls react

# Fix duplicate React
npm dedupe
# or
rm -rf node_modules package-lock.json
npm install

# Ensure matching versions
npm install react@latest react-dom@latest

Common Scenarios & Solutions

The most common cause "" having multiple copies of React in your project.

Diagnosis

Diagnosis
# Check for multiple React versions
npm ls react
# or
yarn why react

# You might see:
# |-- react@18.2.0
# `-- some-library@1.0.0
#   `-- react@17.0.2  <- Duplicate!

Correction: Clean install

Correction: Clean install
# Solution 1: Dedupe
npm dedupe

# Solution 2: Clean install
rm -rf node_modules package-lock.json
npm install

# Solution 3: Use resolutions (package.json)
{
  "resolutions": {
    "react": "18.2.0",
    "react-dom": "18.2.0"
  }
}

# Solution 4: Use overrides (npm 8.3+)
{
  "overrides": {
    "react": "18.2.0",
    "react-dom": "18.2.0"
  }
}

Failure: Package.json

Failure: Package.json
// package.json
{
  "dependencies": {
    "react": "18.2.0",
    "react-dom": "17.0.2"  // Wrong Mismatched version!
  }
}

Correction: Install matching versions

Correction: Install matching versions
# Install matching versions
npm install react@18.2.0 react-dom@18.2.0

# Or use latest for both
npm install react@latest react-dom@latest

Failure: Regular function, not a component

Failure: Regular function, not a component
// Wrong Regular function, not a component
function fetchData() {
  const [data, setData] = useState(null); // Invalid hook call!
  // ...
}

// Wrong Called outside component
const data = useState(null); // Invalid hook call!

function App() {
  return <div>{data}</div>;
}

Correction: Create a custom hook (starts with use )

Correction: Create a custom hook (starts with use )
// Correct Create a custom hook (starts with "use")
function useFetchData() {
  const [data, setData] = useState(null);
  // ...
  return data;
}

// Correct Call hooks inside component
function App() {
  const [data, setData] = useState(null); // Correct Inside component
  return <div>{data}</div>;
}

Failure: When developing a library with npm link

Failure: When developing a library with npm link
# When developing a library with npm link
cd my-library
npm link
cd ../my-app
npm link my-library  # Creates duplicate React!

Correction: Link React from the app to the library

Correction: Link React from the app to the library
# Link React from the app to the library
cd my-app/node_modules/react
npm link
cd ../react-dom
npm link

cd ../../../my-library
npm link react react-dom

# Or use peerDependencies in library
{
  "peerDependencies": {
    "react": ">=16.8.0",
    "react-dom": ">=16.8.0"
  }
}

Best Practices to Avoid This Error

  • Keep React versions in sync - React and React-DOM must match exactly
  • Check for duplicates regularly - Run npm ls react periodically
  • Use peerDependencies for libraries - Don't bundle React in your library
  • Only call Hooks in components or custom hooks - Function names must start with "use"
  • Use npm dedupe after installs - Flatten dependency tree
  • Clean install when in doubt - Delete node_modules and reinstall
  • Use eslint-plugin-react-hooks - Catches Rules of Hooks violations

Code Causes: Breaking the Rules of Hooks

Hooks must run at the top level of a React function component or inside another custom hook. React depends on the order of hook calls staying the same on every render. If a hook is called inside a condition, loop, callback, class component, or normal utility function, React cannot reliably match hook state to the right call.

Custom hooks are allowed because they are part of the React render flow, but they must also follow the same rule. The custom hook name should start with use, and the hook should be called unconditionally by a component or another hook.

  • Call hooks only in function components or custom hooks.
  • Keep hooks above early returns.
  • Move conditions inside useEffect, useMemo, or the custom hook body.
  • Install eslint-plugin-react-hooks to catch mistakes during development.

Package Causes: Duplicate React

React hooks rely on one shared React module instance. If your app imports React from one copy and React DOM renders with another copy, hook internals do not match and React shows the invalid hook call warning.

This often happens with npm link, local component libraries, monorepos, or dependencies that incorrectly list react as a dependency instead of a peer dependency. The fix is to make the app and linked package resolve to the same React copy.

  • Run npm ls react to see installed React copies.
  • Keep react and react-dom on compatible versions.
  • Use peerDependencies for React in reusable libraries.
  • Remove node_modules and reinstall after dependency corrections.

Wrong: Hook Inside a Normal Function

Wrong: Hook Inside a Normal Function
import { useState } from "react";

function readCounter() {
  const [count] = useState(0); // Wrong: not a component or custom hook
  return count;
}

Correct: Move Hook into Component or Custom Hook

Correct: Move Hook into Component or Custom Hook
import { useState } from "react";

function useCounter() {
  const [count, setCount] = useState(0);
  return { count, setCount };
}

export default function Counter() {
  const { count, setCount } = useCounter();
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
Before you move on

Invalid hook call warning in React Fix Mastery Check

5 checks
  • Check whether every hook is called at the top level.
  • Check whether any hook is inside an if, loop, callback, or normal function.
  • Run npm ls react and confirm there is only one compatible React version.
  • Confirm react and react-dom versions match.
  • Check linked packages and local libraries for duplicate React installs.

Try this next

React JS Invalid Hook Call Repair Drills

0 of 2 completed

  1. Use the package tree to find a linked library that installs React directly, move React to a compatible peer dependency, and verify one runtime copy remains. The renderer and component library must resolve the same React instance.
  2. Move a hook call out of a normal function into a component or custom hook, then run the Hooks lint rules and the affected test. A custom hook name alone is not enough; it must execute only in a valid React render context.

React JS Questions Learners Ask

Hooks depend on the React instance used by the renderer. If an app loads one copy of react and react-dom or a linked library loads another copy, the hook call may look valid in your component but still fail because it is connected to a different React module instance.

Run npm ls react from the app root. In Yarn projects, yarn why react can show why each copy is installed.

First fix the dependency relationship, not only node_modules. Shared component libraries should usually declare react and react-dom as peer dependencies, not bundle their own private copies.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.