Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use React hooks in my component library?

I'm currently creating a component library which is included in a Nextjs project via NPM link and having a hard time getting it to consistently load without errors. The latest one is

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

This is a Typescript component, but as far as I can tell, what I've done is okay but it's just not playing sport. Here's the code:

        import React, { useEffect } from "react";
        import { FlagIcon } from "react-flag-kit";

        const LanguageSwitcher = () => {
            useEffect(() => {
                alert('Yo!');
            })
            return (
                <div className="w-full justify-end">
                    <button>
                        <div className="flex items-center">
                            <FlagIcon code="GB" /> <span className="block ml-2">English</span>
                        </div>
                    </button>
                </div>
            )
        }

        export default LanguageSwitcher

This is then being imported into another component in the library and then imported into the Nextjs page. Which is where the error is showing up.

I'm not sure if it's a webpack or typescript compiling issue, tried all the different targets I can think of, tried googling all sorts of things but nothing seems relevant to my situation. It might not even be a React issue but one with Typescript and Webpack, but my exposure to those is very new.

My webpack config:

        var path = require('path');
        module.exports = {
          entry: './src/index.ts',
          devtool: "source-map",
          output: {
            path: path.resolve(__dirname, 'build'),
            filename: 'index.js',
            libraryTarget: 'commonjs2'
          },
          module: {
            rules: [
              {
                test: /\.ts(x?)$/,
                use: 'ts-loader',
                exclude: /node_modules/,
              },
              {
                enforce: "pre",
                test: /\.js$/,
                loader: "source-map-loader"
              }
            ]
          },
          resolve: {
            extensions: [ '.tsx', '.ts', '.js' ],
          }
        };

My tsconfig.json


    {
      "compilerOptions": {
        "outDir": "build",
        "module": "esnext",
        "target": "es6",
        "lib": ["es6", "dom", "es2016", "es2017"],
        "sourceMap": true,
        "allowJs": false,
        "jsx": "react",
        "declaration": true,
        "moduleResolution": "node",
        "forceConsistentCasingInFileNames": true,
        "noImplicitReturns": true,
        "noImplicitThis": true,
        "noImplicitAny": true,
        "strictNullChecks": true,
        "suppressImplicitAnyIndexErrors": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "allowSyntheticDefaultImports": true
      },
      "include": ["src"],
      "exclude": ["node_modules", "build"]
    }

Any pointers or help would be really appreciated!

I also tried reverting everything back to vanilla JS and the problem persists, so I think it might be webpack related?

Edit

Here is my full package.json file and also what Nextjs has

{
  "name": "some/package",
  "version": "1.0.0",
  "description": "",
  "main": "build/index.js",
  "scripts": {
    "test": "jest",
    "start": "webpack --watch --mode=development",
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "16.10.2",
    "webpack": "^4.41.1"
  },
  "devDependencies": {
    // ...
    "@types/react": "^16.9.5",
    "@types/react-dom": "^16.9.1",
    "react": "16.10.2",
    "react-dom": "^16.10.2",
    "ts-loader": "^6.2.0",
    "typescript": "^3.6.4",
    "webpack-cli": "^3.3.9"
  }
}
    "react": "16.10.2",
    "react-dom": "16.10.2"
like image 882
Alec Ritson Avatar asked Oct 14 '19 19:10

Alec Ritson


1 Answers

Turns out this was due to issues with the symlinked react in the component library

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

Fixed by running the steps in the link:

npm link ../myapp/node_modules/react // Run within the component library
like image 169
Alec Ritson Avatar answered Nov 01 '22 05:11

Alec Ritson