Hooks and multiple instances of React in Gatsby app

Viewed 551

I'm trying to use useState in a simple function component in GatsbyJS but I'm getting a seemingly common error in React.

My stripped-down component:

import React, { useState } from 'react';

export default function Header () {
    const [isOpen, toggleOpen] = useState(false);
    return ( 
        <header>
            <button onClick={() => toggleOpen( !isOpen )}>Click Me</button>
        </header>
    )
}

I get the following 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 app See redacted to quell SO error for tips about how to debug and fix this problem.

So I read up about the error on this Facebook/React docs page and have determined that my react-dom version is >16.8.0 (I'm using ^16.13.1). My react version is the same.

I'm pretty sure there's nothing wrong with my component function (I basically copied the example from the docs).

The third thing, which I suspect is the issue, is multiple versions of react running simultaneously. When I run npm ls react I get:

+-- gatsby@2.24.73
| `-- gatsby-cli@2.12.107
|   `-- react@16.13.1  deduped
`-- react@16.13.1

I tried moving react and react-dom to peerDependencies, as per this response from this Github issues thread, in my `package.json' but that didn't fix the problem, e.g:

"peerDependencies": {
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  }

I also tried adding a GATSBY_HOT_LOADER = “fast-refresh” var in a .env.development file according to this Gatsby thread but the issue persisted.

require("dotenv").config({
    path: `.env.${process.env.NODE_ENV}`,
}) 

Here's my package.json

{
  "name": "gatsby-starter-hello-world",
  "private": true,
  "description": "A simplified bare-bones starter for Gatsby",
  "version": "0.1.0",
  "license": "0BSD",
  "scripts": {
    "build": "gatsby build",
    "develop": "gatsby develop",
    "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
    "start": "npm run develop",
    "serve": "gatsby serve",
    "clean": "gatsby clean",
    "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
  },
  "dependencies": {
    "gatsby": "^2.24.73",
    "gatsby-image": "^2.4.21",
    "gatsby-plugin-sass": "^2.3.16",
    "gatsby-plugin-sharp": "^2.6.40",
    "gatsby-source-filesystem": "^2.3.34",
    "gatsby-transformer-sharp": "^2.5.17",
    "hamburgers": "^1.1.3",
    "node-sass": "^4.14.1",
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },
  "devDependencies": {
    "eslint-plugin-react-hooks": "^4.1.2",
    "prettier": "2.1.2"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/gatsbyjs/gatsby-starter-hello-world"
  },
  "bugs": {
    "url": "https://github.com/gatsbyjs/gatsby/issues"
  }
}

And environment info:

System:
    OS: Windows 10 10.0.18362
    CPU: (8) x64 Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
  Binaries:
    Node: 12.16.1 - C:\Program Files\nodejs\node.EXE
    npm: 6.13.4 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: 44.18362.449.0
  npmPackages:
    gatsby: ^2.24.73 => 2.24.73
    gatsby-image: ^2.4.21 => 2.4.21
    gatsby-plugin-sass: ^2.3.16 => 2.3.16
    gatsby-source-filesystem: ^2.3.34 => 2.3.34

I've been using Gatsby without issues for some time now so I'm surprised by this error. I suspect it has to do with Gatsby running a version of React, although "deduped", and another version of React also running as seen when I run npm ls react.

Where can I go from here?

Thanks,

2 Answers

I'm also using React@16.13.1. Notably, the gatsby-starter currently only uses React@16.12.1. I ultimately came across an answer from Jeremy Albright on the Gatsby Spectrum that pointed out this could be related to react-hot-loader being deprecated.

Gatsby already has support instead for fast-refresh, you just have to enable the flag.

The fix that worked for me was to add GATSBY_HOT_LOADER=fast-refresh to my .env file.

Source

So I ended up starting over and downloading a fresh copy of the gatsby-starter I was using and that's resolved the issue.

I think I inadvertently installed react and react-dom while I was trying to install a plugin at some point and having multiple versions of react running (one within gatsby) and one installed somewhere else in my project caused the issue.

Related