question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Hooks error from external component

See original GitHub issue

Do you want to request a feature or report a bug? bug

What is the current behavior? We are trying to create an external module which will be imported in main app. Here is the module :

export const MyHelloComponent = (props) => {
  const [test, setTest] = useState();
  return (<div>Hello</div>);
}

Importing this simple code into main app gives us the error :

Uncaught Invariant Violation: Hooks can only be called inside the body of a function component

Removing hooks this code works fine.

We have followed instructions from https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react but error still thrown

If we link react as mentionned in documentation, works but it only can be done in development not in production.

We are not the only one having this issue Side package with React Hooks failing with Invariant Violation when called in main package

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn’t have dependencies other than React. Paste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:

Code from external component : package.json

{
  "name": "app-component",
  "version": "1.0.0",
  "main": "build/index.js",
  "license": "MIT",
  "private": true,
  "peerDependencies": {
    "react": "^16.8.4",
    "react-dom": "^16.8.4"
  },
  "devDependencies": {
    "@babel/core": "^7.3.4",
    "@babel/plugin-proposal-class-properties": "^7.3.4",
    "@babel/plugin-proposal-object-rest-spread": "^7.3.4",
    "@babel/plugin-transform-react-jsx": "^7.3.0",
    "@babel/plugin-transform-regenerator": "^7.3.4",
    "@babel/preset-env": "^7.3.4",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "css-loader": "^2.1.0",
    "react": "^16.8.4",
    "react-dom": "^16.8.4",
    "style-loader": "^0.23.1",
    "styled-jsx": "^3.2.1",
    "webpack": "^4.29.5",
    "webpack-cli": "^3.2.3"
  },
  "scripts": {
    "build": "./node_modules/.bin/webpack --mode production",
    "dev": "./node_modules/.bin/webpack --mode development --watch"
  },
  "files": [
    "build"
  ],
  "dependencies": {
    "@material-ui/core": "^3.9.2"
  }
}

webpack.config.js

const path = require('path');
const pkg = require('./package.json');

const libraryName= pkg.name;

module.exports = (env, argv) => ({
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'index.js',
    library: libraryName,
    libraryTarget: 'commonjs2',
    publicPath: '/build/',
  },
  devtool: argv.mode !== 'production' ? 'inline-source-map': false,
  module: {
    rules: [
      {
        test: /\.js$/,
        include: path.resolve(__dirname, 'src'),
        exclude: /(node_modules|bower_components)/,
        use: ['babel-loader']
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
    ]
  },

  resolve: {
    alias: {
      'react': path.resolve('./node_modules/react'),
      'react-dom': path.resolve('./node_modules/react-dom'),
    }
  },
  externals: {
    react: "react",
    "react-dom": "react-dom"
  }
});

src/index.js

export * from './components/hello';

src/components/hello.js

import React, { useState } from 'react';
export const MyHelloComponent = (props) => {
  const [test, setTest] = useState();
  return (<div>Hello</div>);
}

Code from main app: webpack.config.js

module.exports = {
  entry: './src/index.js',
  output: {
    path: __dirname + '/dist',
    publicPath: '/dist/',
    filename: 'bundle.js'
  },
  devServer: {
    contentBase: './public',
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      }
    ]
  },
};

package.json

{
  "name": "react-app-shell",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "webpack-dev-server --mode development"
  },
  "dependencies": {
    "react": "^16.8.4",
    "react-dom": "^16.8.4"
  },
  "devDependencies": {
    "@babel/core": "^7.3.4",
    "@babel/preset-env": "^7.3.4",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.2.3",
    "webpack-dev-server": "^3.2.1"
  }
}

src/index.js

import React from "react";
import ReactDOM from "react-dom";
import {MyHelloComponent} from 'app-component';

class Welcome extends React.Component {
  render() {
    return <><h1>Main App</h1><MyHelloComponent/></>;
  }
}
ReactDOM.render(<Welcome />, document.getElementById("root"));

To be able to make it works, you have to do yarn link after (or before) having built it from component and yarn link "app-component" from main app.

What is the expected behavior? use hooks from external components works obviously.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React? React 16.8.4 and with previous version it doest not work too

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:14
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

3reactions
rameshirreplaceablecommented, Jul 13, 2021

Hi guys, i have fixed this issue please try this out.

Component composition issue react

i really liked its has detailed info about external component related issue

2reactions
ghostcommented, Apr 16, 2020

If there any one still stucked with this problem, Please check if you import react like this somewhere:

import React from 'React'

and

import React from 'react'

This causes bundler to import two React modules, as Dan pointed. ( https://github.com/facebook/react/issues/15050#issuecomment-470515270 ) I spent too much time because of this mistake. 😸

Read more comments on GitHub >

github_iconTop Results From Across the Web

Invalid Hook Call Warning - React
You are probably here because you got the following error message: Hooks can only be called inside the body of a function component....
Read more >
Invalid hook call. Hooks can only be called inside of the body ...
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the...
Read more >
"Hooks can only be called inside the body of a function ...
Most common: You're breaking the rules of hooks. You must only call hooks while React is rendering a function component. #The rules of...
Read more >
Solving React Hooks' invalid hook call warning - Rob Kendal
Building a React project and have the error 'Hooks can only be called inside the body of a function component'? We'll solve the...
Read more >
Controller | React Hook Form - Simple React forms validation
React Hook Form embraces uncontrolled components and native inputs, however it's hard to avoid working with external controlled component such as ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found