react: Hooks error on React library compiled with Rollup.js

Disclaimer: I’m not sure if this is an specific bug from React’s Hooks or it is something I’m missing in my Rollup.js configuration but I’ve been trying a lot of different things and always end up in the same error.

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

I’m building a React Component library using the alpha version of React and Hooks, and using Rollup.js v1.1.2 as a bundler with the next configuration:

import { readdirSync } from 'fs';
import path from 'path';
import babel from 'rollup-plugin-babel';
import commonjs from 'rollup-plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import replace from 'rollup-plugin-replace';
import resolve from 'rollup-plugin-node-resolve';
import { terser } from 'rollup-plugin-terser';

const CODES = [
  'THIS_IS_UNDEFINED',
  'MISSING_GLOBAL_NAME',
  'CIRCULAR_DEPENDENCY',
];

const getChunks = URI =>
  readdirSync(path.resolve(URI))
    .filter(x => x.includes('.js'))
    .reduce((a, c) => ({ ...a, [c.replace('.js', '')]: `src/${c}` }), {});

const discardWarning = warning => {
  if (CODES.includes(warning.code)) {
    return;
  }

  console.error(warning);
};

const env = process.env.NODE_ENV;

const plugins = [
  external(),
  babel({
    exclude: 'node_modules/**',
  }),
  resolve(),
  replace({ 'process.env.NODE_ENV': JSON.stringify(env) }),
  commonjs(),
  env === 'production' && terser(),
];

export default [
  {
    onwarn: discardWarning,
    input: 'src/index.js',
    output: {
      esModule: false,
      file: 'umd/library-name.js',
      format: 'umd',
      name: 'libraryName',
    },
    plugins,
  },
  {
    onwarn: discardWarning,
    input: getChunks('src'),
    output: [
      { dir: 'esm', format: 'esm', sourcemap: true },
      { dir: 'cjs', format: 'cjs', sourcemap: true },
    ],
    plugins,
  },
];

For the examples page I created an internal project using create-react-app and I’m importing the library in the package.json using link:..

The page breaks as soon as it gets to the first Hooks call var svgRef = useRef(); with the error mentioned above, but this only happens when I’m using the bundled code from the ESM file not when I’m using the library code directly. That’s why I’m not sure if it is a Rollup misconfiguration or a React Hooks bug.

I appreciate any help or guidance on this.

React v16.8.0-alpha.1 React DOM v16.8.0-alpha.1 OS: macOS Browser: Chrome Node.js v11.8.0

I did test it with a previous alpha version of React and it happens the same.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 10
  • Comments: 29

Most upvoted comments

You probably have two Reacts.

@ghostjzf if your problem is because of linking the package locally (and not installing from npm repository), then https://github.com/facebook/react/issues/13991#issuecomment-435587809 solves the problem.

If not that, then the problem is that you should add react as an external dependency in your rollup config, e.g:


  external: [
    'react',
    'react-dom',
  ],

I can’t guess what’s wrong in your particular setup but I’ve described the issue: you’ll see it when you have two Reacts in the resulting bundle. Check the bundle contents. I can’t help you with setting up Rollup, what its errors mean, or how Node resolutions works — just the React part which is definitely related to that.

Npm link is known for causing this because webpack would “see” React both in your lib folder and in your app folder, and would include both of them in the bundle. A common workaround is to npm link back from your lib’s node_modules/react into your app’s React copy.

Hello @eduardosanzbBCG I did solve it. Check out the configuration file I have for Rollup. Is working great!

@davegomez do you have any update on the issue? Did you solved it?

(Currently having the same issue, plus I’m also using typescript) Thanks!

Update I solved it following this comment

Not sure if that will help anyone, but what worked for me was:

  • in rollup.config.js setting up externals, just like @adraeth mentioned before, so:
  external: [
    'react',
    'react-dom',
  ],
  • remove react and react-dom from the dependencies and move them to peerDependencies
  • and (I can’t stress this enough) remove and reinstall node_modules

Hope that helps 🤞

@ghostjzf if your problem is because of linking the package locally (and not installing from npm repository), then #13991 (comment) solves the problem.

If not that, then the problem is that you should add react as an external dependency in your rollup config, e.g:


  external: [
    'react',
    'react-dom',
  ],

thank you for your help, but when I use the “npm link” to test it, it’s also facing the same problem

@gaearon … I think this issue is not just happening because of two versions of react, When we use hooks in a component library and bundle it as ES6 distribution, hooks are pushed inside conditions (like if) and we are getting this error. I am including library as file:…/ Can you please tell how to overcome this.

This was rough, and I learned a lot, but in the end what worked for me was manually editing (in MyLib that’s sym-linked into MyProject) the build output dist/index.esm.js file, and changing the import of React:

// change this
import React from 'react';
// to this
import React from '../../../MyProject/node_modules/react';

It’s annoying, and I changed the build script in my lib to do this for me, but it was so sweet when it WORKED:

// in package.json scripts field
  "build": "npx rollup -c && npm run fixreact",
  "fixreact": "sed -i 's+react+../../../bgio/battlescape/node_modules/react+' ./dist/index.esm.js",

Hope this helps any other stuck folks, I’m on linux so your sed command might be different.

I don’t think this is the case @gaearon so I would like to provide a little bit more context to see if might be something else.

I have React, React DOM, and Styled Components as peer dependencies of my library:

  "dependencies": {
    "color": "^3.1.0",
    "d3-array": "^2.0.3",
    "d3-axis": "^1.0.12",
    "d3-format": "^1.3.2",
    "d3-scale": "^2.1.2",
    "d3-selection": "^1.4.0",
    "d3-shape": "^1.3.3",
    "d3-time-format": "^2.1.3",
    "d3-transition": "^1.2.0",
    "date-fns": "^2.0.0-alpha.27",
    "ramda": "^0.26.1"
  },
  "devDependencies": {
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.3.1",
    "@babel/preset-react": "^7.0.0",
    "cross-env": "^5.2.0",
    "flow-bin": "^0.91.0",
    "jest-styled-components": "^6.3.1",
    "react-scripts": "^2.1.3",
    "react-test-renderer": "^16.8.0-alpha.1",
    "rollup": "^1.1.2",
    "rollup-plugin-babel": "^4.3.2",
    "rollup-plugin-commonjs": "^9.2.0",
    "rollup-plugin-node-resolve": "^4.0.0",
    "rollup-plugin-peer-deps-external": "^2.2.0",
    "rollup-plugin-replace": "^2.1.0",
    "rollup-plugin-terser": "^4.0.3"
  },
  "peerDependencies": {
    "react": "^16.8.0-alpha.1",
    "react-dom": "^16.8.0-alpha.1",
    "styled-components": "^4.1.3"
  }

Besides having React as a peerDependency I have to install it as a devDependency otherwise I’m getting this error (but I think this is a different issue):

Failed to compile.

../esm/index.js
Module not found: Can't resolve 'react' in '/Users/user/library/esm'

The internal examples page has the following package.json file:

{
  "name": "examples",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "normalize.css": "^8.0.1",
    "react": "^16.8.0-alpha.1",
    "react-dom": "^16.8.0-alpha.1",
    "react-scripts": "2.1.3",
    "library-name": "link:..",
    "styled-components": "^4.1.3"
  },
  "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"
  ]
}

And if I check the node_modules directory only one version of React is installed.

Please let me know if I can provide mode information on this? I would code a pen or something trying to replicate what is happening but I’m not sure if I can do a pen to replicate the Rollup part.

I’m gonna try to publish the code soon in case it might be of some help.

Update

I just try to use the library using npm link from an external create-react-app project using the same configuration and I got the same result. I still need to add React as a devDependency and now I’m getting a different error if I use the production build (a Webpack related error) I guess from create-react-app.

This was rough, and I learned a lot, but in the end what worked for me was manually editing (in MyLib that’s sym-linked into MyProject) the build output dist/index.esm.js file, and changing the import of React:

// change this
import React from 'react';
// to this
import React from '../../../MyProject/node_modules/react';

It’s annoying, and I changed the build script in my lib to do this for me, but it was so sweet when it WORKED:

// in package.json scripts field
  "build": "npx rollup -c && npm run fixreact",
  "fixreact": "sed -i 's+react+../../../bgio/battlescape/node_modules/react+' ./dist/index.esm.js",

Hope this helps any other stuck folks, I’m on linux so your sed command might be different.

Wow I was losing my mind all day and this was the only thing that worked for me, thank you!