Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hooks can only be called inside the body of a function component error

Whenever I try and use a hook in my app, I get the Hooks can only be called inside the body of a function component error. I'm using a standard webpack4/babel config, with preset-env and preset-react plugins. My react/react-dom versions are pinned to 16.8.4 using yarn resolutions, so there should not be a mismatch in React/dom versions.

This is on the most basic of usages:

import React, { useState } from "react";

function MyComp() {
  const [hello] = useState(0);

  return <div>HELLO {hello}</div>;
}
export default MyComp;

I have checked the gotchas listed https://reactjs.org/warnings/invalid-hook-call-warning.html with no luck.

Is there anything else that I need to include?

Stack Snippet version from T.J. Crowder (which works):

const { useState } = React;

function MyComp() {
  const [hello] = useState(0);

  return <div>HELLO {hello}</div>;
}

ReactDOM.render(
  <MyComp />,
  document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

EDIT: Debugging the error reveals that

function resolveDispatcher() {
  var dispatcher = ReactCurrentDispatcher.current;
  !(dispatcher !== null) ? invariant(false, 'Hooks can only be called inside the body of a function component. (/* omitted url due to warning */ )') : void 0;
  return dispatcher;
}

in react.development such that dispatcher is null. Would this still suggest that I am not using the correct version of React/DOM, even though yarn list informs me that they're both at 16.8.4?

EDIT2: console.log-ing a count in the parent's render function reveals

let count = 0;
class App extends Component {
  render() {
    count++;
    console.log("counter", count++);

    return (
      <MyComp />
    );
  }
}

export default App;

Actually runs twice:

VM239 bundle.js:141088 counter 1
App.js:46 counter 1

which is very interesting - I can't explain why that would occur (my app had otherwise ran fine before I tried this experiment - but it would suggest that there could be two competing processes in conflict

like image 653
bak202 Avatar asked Mar 04 '23 08:03

bak202


1 Answers

The problem was with my webpack config - I was using both the HtmlWebpackPlugin whilst adding the output bundle's script tag to my index.html, as described here: All my code runs twice when compiled by Webpack

This meant that React was being included twice, causing the error. Sadly, all of my previous checks were over different versions, not 2 instances of the same version!

like image 113
bak202 Avatar answered Apr 14 '23 02:04

bak202