react: 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:

Hi all, I am new to react and I am trying to create a react library of components and I came across this problem because one of the components I am creating uses REACT HOOKS.

Disclaimer: this is my first time creating an issue, so please bear with me.

So I am trying to create an accordion component which toggles between these classes accordion__item--open and accordion__item to open and close.

package.json

{
  "name": "react-lib",
  "version": "0.3.0",
  "description": "A simple UI library of react components",
  "main": "dist/index.js",
  "publishConfig": {
    "registry": ""
  },
  "scripts": {
    "login": "",
    "build": "webpack --mode=production",
    "develop": "webpack --mode=development --watch"
  },
  "repository": {
    "type": "git",
    "url": ""
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "homepage": "",
  "dependencies": {
    "@babel/core": "^7.3.4",
    "@babel/preset-env": "^7.3.4",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "eslint": "^5.15.1",
    "eslint-loader": "^2.1.2",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.2.3",
    "webpack-node-externals": "^1.7.2"
  },
  "devDependencies": {
    "eslint-config-airbnb": "^17.1.0",
    "eslint-plugin-import": "^2.16.0",
    "eslint-plugin-jsx-a11y": "^6.2.1",
    "eslint-plugin-react": "^7.12.4",
    "eslint-plugin-react-hooks": "^1.6.0"
  }
}

webpack.config.js

const path = require('path');
const webpack = require('webpack');

module.exports =  {

  mode: 'development',
  optimization: {
    minimize: true,
  },
  entry: './index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'index.js',
    library: '',
    libraryTarget: 'commonjs'
  },
  target: 'node',
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env', '@babel/react']
        }
      }
    ]
  } 
};

This is the accordion container:

import React from 'react'; 

function Accordion({ children }) {

 return (
   <div className="accordion">
     { children }
   </div>
 ); 

}

export default Accordion;

This is the accordion item that will live inside the container:

import React, { useState } from 'react'; 

function AccordionItem({header, content}) { 

const [ isActive, toggleActive ] = useState(false);
  
return (
    <div className={ `accordion__item ${ isActive ? 'accordion__item--open' : '' }` }>

      <button
        className="accordion__item-header"
        onClick={ () => isActive ? toggleActive(false) : toggleActive(true) }
      >
       { header }
       <svg className="icon icon--debit" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
         <path className="icon__path" d="M22.37,22.33V2.67a2.63,2.63,0,0,1,5.26,0V47.24a2.63,2.63,0,0,1-5.26.09V27.58H2.71a2.63,2.63,0,0,1,0-5.25Zm11.92,5.25a2.63,2.63,0,0,1,0-5.25h13a2.63,2.63,0,0,1,0,5.25Z">
         </path>
       </svg>
     </button>

     <div className="accordion__item-content">
       { children }
     </div>

   </div>
 )

};

export default AccordionItem;

Now inside of a create-react-app I import these components

My library and the create-react-app are relative to each other and I am using npm link

import React from 'react'; 

import {AccordionItem} from 'react-lib'
import {Accordion} from 'react-lib';

function App ({props}) {

  return (
    
      <Accordion>
        <AccordionItem header={"Hello"} content={"World"}/>
      </Accordion> 
  )

}

export default App;

I have followed all of these instructions and I still get the same error.

Current behavior?

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 app
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.

Steps to reproduce

Expected behavior

  • It should show a button with a “plus” svg sign and the words “Hello” and “World” respectively
  • Open devtools and go to elements
  • When clicking on the button the class accordion_item--open should toggle

To see the above, do the following:

  • Uncomment these lines at myapp/src/App.js
import Accordion  from './Accordion';
import AccordionItem from './AccordionItem';
  • The comment out these line, alse at myapp/src/App.js:
import { Accordion } from 'react-lib';
import { AccordionItem } from 'react-lib';

Versions of React, Browser / OS are affected by this issue:

  • React and React-Dom: both are ^16.8.6 on both react-lib and the myapp
  • Browser: Brave Version 0.61.52 Chromium: 73.0.3683.86 (Official Build) (64-bit)
  • OS: MacOS High Siera Version 10.13.6 (17G5019)

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 82
  • Comments: 70 (7 by maintainers)

Most upvoted comments

My library and the create-react-app are relative to each other and I am using npm link

Did you read this part?

https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react

It directly addresses the link workflow:

Screen Shot 2019-04-04 at 09 28 47

This happens if i use hook inside a HOC.

const HOC = Component => {
  return (props) => {
    const [val] = useState();
    return <div>{val}</div>
  }
}

I solve this by change

                <Route key={index} render={route.component} path={route.path} />

to

                <Route key={index} component={route.component} path={route.path} />

but I don’t know why 😦

@carlosriveros Case 1: You might be check your index.html that only have one script tag bundle

If you get the same error after you check index.html Case 2: If you use Webpack html, In plugins property inside webpack.config file And not have {reject: true} in option of new HTMLWebpackPlugin();

You must remove script tag that src to your bundle in index.html

Because HTMLWebpackPlugin will add script tag that include your bundle file automatically.

I just call hook in a very very basic way.

import React, {useState} from 'react'
import ReactDOM from 'react-dom'

function App() {
const [number, setNumber] = useState(0);
const increase = () => {
    setNumber(number+1);
}
return <div>
<span>Counting: {number}</span>
<button onClick={increase} >Increase</button>
</div>
}

const selector = document.getElementById('app');

ReactDOM.render(<App />, selector);

I get Error Hooks can only be called inside of the body of a function component. I have create a lot of react project from sketch but I never get this error before. I understand all rules of hook. I spend a time for 12 hours to debug and solve it, But unfortunately I can’t, Now I have no idea.

// 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); // I get true

Fixed by using component instead of render by mistake. The official guide didn’t mention this scenario. Thanks, xyj404 <Route path="/login" exact component={LoginForm} />

there is a nice webpack configuration solution to pointing to the same/single react instance. It was to add a resolutions inside the app that is using the ‘to be npm module’.

inside webpack.config.js, add alias to react - so it uses that one react instance :

module.exports = {
resolve: {
    alias: {
      react: path.resolve('./node_modules/react')
    }
  },
 // other webpack settings
}

from
<Route path=“/component” render={myComponent} />

to <Route path=“/component” component={myComponent} />

I have been testing all solutions about this hooks problem, any import of a component from an external lib using hooks will crash as there is 2 reacts instances (one from the lib, one from my app).

I’ve followed all suggestions, nothing has been working so far. I’m gonna make component with a state until it gets clarified further …

For anyone using lerna, you may come across this problem when running tests in one package, where the code references components in another package.

The problem that we experienced in this case was due to react being imported in the spec, and also being imported in a component in the component tree that was using Material UI’s withStyles, which is implemented using hooks in Material UI.

It seems that react internally manages state in a ReactCurrentDispatcher.current variable, and this ends up getting set in one instance of react, but used in the other instance of react – when it’s empty, it throws the Invalid hook call ... message.

We were already using Craco to override Create React App’s webpack config at build time:

  webpack: {
    alias: {
      react: path.resolve(__dirname, './node_modules/react'),
    },
  },

However, this webpack override is only used at build time – when running the tests, the code isn’t built, but instantiated from source – so our solution was to make use of CracoAlias in our craco.config.js to specify the react path during the tests:

  plugins: [
    {
      plugin: CracoAlias,
      options: {
        source: 'options',
        baseUrl: './',
        aliases: {
          // We need to alias react to the one installed in the desktop/node_modules
          // in order to solve the error "hooks can only be called inside the body of a function component"
          // which is encountered during desktop jest unit tests,
          // described at https://github.com/facebook/react/issues/13991
          // This is caused by two different instances of react being loaded:
          // * the first at packages/desktop/node_modules (for HostSignUpDownloadComponent.spec.js)
          // * the second at packages/components/node_modules (for packages/components/Modal)
          react: './node_modules/react',
        },
      },
    },
  ],

lerna can cause this problem, as I’ve learned (lerned?) today.

lerna users, if you are developing a component library, do not include react in your library’s dependencies, put it in your peerDependencies and @types/react in your devDependencies.

from

<Route path="/component" component={myComponent} />

to

<Route path="/component"><myComponent /></Route>

-_-

This happens if i use hook inside a HOC.

const HOC = Component => {
  return (props) => {
    const [val] = useState();
    return <div>{val}</div>
  }
}

I am also facing the same issue.

https://stackoverflow.com/questions/59173968/react-error-hooks-can-only-be-called-inside-the-body-of-a-function-component?noredirect=1#comment104570333_59173968

can you please guide me ?

I solve with removing yarn.lock, package-lock.json, node_modules, dist, kind of cache and build files and then run yarn or npm install for install libraries again. Now it works!

Hi there, I am new to React Hooks. I just used Material-UI for creating Search Bar in my project. I wrote this code, but this is not working and giving the same issue. I read React Hooks docs but not got nothing regarding this. REACTJS CODE

import { makeStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
import InputBase from '@material-ui/core/InputBase';
import IconButton from '@material-ui/core/IconButton';
import SearchIcon from '@material-ui/icons/Search';

const useStyles = makeStyles({
  root: {
    padding: '2px 4px',
    display: 'flex',
    alignItems: 'center',
    width: 400,
  },
  input: {
    marginLeft: 8,
    flex: 1,
  },
  iconButton: {
    padding: 10,
  },
  divider: {
    width: 1,
    height: 28,
    margin: 4,
  },
});

function Feature() {
    const classes = useStyles();

  return (
    <Paper className={classes.root}>
      <InputBase className={classes.input} placeholder="Search Google Maps" />
      <IconButton className={classes.iconButton} aria-label="Search">
        <SearchIcon />
      </IconButton>
    </Paper>
  );
}

export default Feature;

PACKAGE.JSON

  "name": "builder-frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@material-ui/core": "^4.0.1",
    "@material-ui/docs": "^3.0.0-alpha.9",
    "@material-ui/icons": "^4.0.0",
    "@material-ui/styles": "^4.0.1",
    "react": "^16.8.5",
    "react-dom": "^16.8.5",
    "react-redux": "^6.0.1",
    "react-router-dom": "^5.0.0",
    "react-scripts": "2.1.8",
    "redux": "^4.0.1",
    "styled-components": "^4.2.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

VERSION

  • Node – v10.15.3
  • React – ^16.8.5
  • Material-UI – ^4.0.1

EXPECTED RESULT

  • Built-in VS CODE and expected A search bar OUTPUT TypeError: Object(…) is not a function 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:

TRY Try to run in CODESANDBOX, everything runs fine Check it.

I just call hook in a very very basic way.

import React, {useState} from 'react'
import ReactDOM from 'react-dom'

function App() {
const [number, setNumber] = useState(0);
const increase = () => {
    setNumber(number+1);
}
return <div>
<span>Counting: {number}</span>
<button onClick={increase} >Increase</button>
</div>
}

const selector = document.getElementById('app');

ReactDOM.render(<App />, selector);

I get Error Hooks can only be called inside of the body of a function component. I have create a lot of react project from sketch but I never get this error before. I understand all rules of hook. I spend a time for 12 hours to debug and solve it, But unfortunately I can’t, Now I have no idea.

// 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); // I get true

You might have mismatching versions of React and React DOM. I had same issue solved by making change in React version

If you’re using lerna or a monorepo like me, add sth like this to your Webpack resolve config

...
    alias: {
      'react-dom': 'path/to/main-package/node_modules/react-dom',
      react: 'path/to/main-package/form/node_modules/react',
	}
...

If you’re getting it in Storybook, add it to custom Webpack config there too.

A side note, if this fixes the issue for you, your webpack built bundle also had 2 versions of react in it (use sth like webpack bundle analyzer to inspect it). In my case, I had a separate package in my monorepo that took care of bundling and all the tooling so I had to add an alias.

Yeah, I had same issue when I use @material-ui. It takes more time to figure out this issue. Then I searched google and found a solution for this. It’s here http://putridparrot.com/blog/react-material-ui-invalid-hook-call-hooks-can-only-be-called-inside-of-the-body-of-a-function-component/

Original post:

When looking through some examples of writing Material UI code within React and using TypeScript (within a .tsx file to be precise) you might come across an error at runtime such as “Invalid hook call. Hooks can only be called inside of the body of a function component”.

Here’s an example of the code which causes this error

import React, { Component }  from "react";
import AddIcon from "@material-ui/icons/Add";
import { Fab } from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
 
const useStyles = makeStyles(theme => ({
   fab: {
      margin: theme.spacing(1),
   },
}));
 
const classes = useStyles();
 
export default class SampleComponent extends Component<{}, {}> {
   public render() {
      return (
         <div>
            <Fab color="primary" aria-label="Add" className={classes.fab}><AddIcon /></Fab>
         </div>
       );
   }
}

What we need to do is wrap the useStyles code in a function and replace the code which uses it, so for example

const SampleFab = () => {
   const classes = useStyles();
   return <Fab color="primary" aria-label="Add" className={classes.fab}><AddIcon /></Fab>;
}
 
export default class SampleComponent extends Component<{}, {}> {
   public render() {
      return (
         <div>
            <SampleFab />
         </div>
      );
   }
}

This also shows how we can create reusable components from just a simple function.

=> It’s crazy but It’s working well. Hope this can help.

I followed the instructions provided in the help page but it still didn’t resolve the problem

I had the same problem but the cause was different. For anyone using auto-import plugins or snippets make sure you import from the same case react.

If you have mix of import {useEffect} from 'react' and import {useEffect} from 'React' you will run into this issue.

I think you’re facing the same issue as the folks in https://github.com/facebook/react/issues/13991 Could you have a look at some of the workarounds presented at the very bottom of the issue and see of they work for you?

just delete the node_module/react from your lib and try again.

My library and the create-react-app are relative to each other and I am using npm link

Did you read this part?

https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react

It directly addresses the link workflow:

Screen Shot 2019-04-04 at 09 28 47

Thanks a lot for saving my ass ❤️

In my case I was referring to a library from the window object which had a different React version. I ended up using the externals configuration option from webpack which helped me refer to that library’s react and react-dom and made the error go away.

So I believe the reason I was getting this error was because You might have more than one copy of React in the same app.

In my case, I had let match = useRouteMatch("/user/:id"); outside the component, which is a hook from react-router, so the error was right.

I solve this by change

                <Route key={index} render={route.component} path={route.path} />

to

                <Route key={index} component={route.component} path={route.path} />

but I don’t know why 😦

Thanks, Dear, Its worked for me, Still, I am confused, why?

I solve this by change

                <Route key={index} render={route.component} path={route.path} />

to

                <Route key={index} component={route.component} path={route.path} />

but I don’t know why 😦

It does work for me, but I dont know why either.

The “component” prop expects a React component, the “render” prop expects a function that will be invoked as a function. Function components are components, invoking them as normal functions doesn’t work if they use hooks and generally isn’t a good idea.

My library and the create-react-app are relative to each other and I am using npm link

Did you read this part?

https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react

It directly addresses the link workflow:

Screen Shot 2019-04-04 at 09 28 47

This work like a charm!

If you’re using lerna or a monorepo like me, add sth like this to your Webpack resolve config

...
    alias: {
      'react-dom': 'path/to/main-package/node_modules/react-dom',
      react: 'path/to/main-package/form/node_modules/react',
	}
...

If you’re getting it in Storybook, add it to custom Webpack config there too.

A side note, if this fixes the issue for you, your webpack built bundle also had 2 versions of react in it (use sth like webpack bundle analyzer to inspect it). In my case, I had a separate package in my monorepo that took care of bundling and all the tooling so I had to add an alias.

Thank you, that’s solved my problem, I installed another React in my docs dictory, which caused this problem.

Hi there, I am new to React Hooks. I just used Material-UI for creating Search Bar in my project. I wrote this code, but this is not working and giving the same issue. I read React Hooks docs but not got nothing regarding this. REACTJS CODE

import { makeStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
import InputBase from '@material-ui/core/InputBase';
import IconButton from '@material-ui/core/IconButton';
import SearchIcon from '@material-ui/icons/Search';

const useStyles = makeStyles({
  root: {
    padding: '2px 4px',
    display: 'flex',
    alignItems: 'center',
    width: 400,
  },
  input: {
    marginLeft: 8,
    flex: 1,
  },
  iconButton: {
    padding: 10,
  },
  divider: {
    width: 1,
    height: 28,
    margin: 4,
  },
});

function Feature() {
    const classes = useStyles();

  return (
    <Paper className={classes.root}>
      <InputBase className={classes.input} placeholder="Search Google Maps" />
      <IconButton className={classes.iconButton} aria-label="Search">
        <SearchIcon />
      </IconButton>
    </Paper>
  );
}

export default Feature;

PACKAGE.JSON

  "name": "builder-frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@material-ui/core": "^4.0.1",
    "@material-ui/docs": "^3.0.0-alpha.9",
    "@material-ui/icons": "^4.0.0",
    "@material-ui/styles": "^4.0.1",
    "react": "^16.8.5",
    "react-dom": "^16.8.5",
    "react-redux": "^6.0.1",
    "react-router-dom": "^5.0.0",
    "react-scripts": "2.1.8",
    "redux": "^4.0.1",
    "styled-components": "^4.2.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

VERSION

  • Node – v10.15.3
  • React – ^16.8.5
  • Material-UI – ^4.0.1

EXPECTED RESULT

  • Built-in VS CODE and expected A search bar OUTPUT TypeError: Object(…) is not a function 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:

TRY Try to run in CODESANDBOX, everything runs fine Check it.

This happend to me today and I just run npm install --save react-dom@latest

https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react