Material-UI ThemeProvider Invalid hook call when building an ES6 module using rollupJs

Viewed 1854

the problem here is quite simple, really. I'm currently working on an app that I want to split parts into components. I decided to create a boilerplate to create modules using rollupJS in order to export these modules into my core app using NPM.

I stumbled upon a problem while using MaterialUI in my dependencies, and while using withStyles and ThemeProvider from the module.

I've currently tried :

  • building the module as cjs (commonJS) instead of es6 module, not working,
  • passing material-ui as smthg else than peerDependencies, little to none effects,
  • ran different scenario using rollup (changing orders, using externalPeerDependencies plugin and so on) but I don't understand rollup that much, so that's a dead end to me, and I'd like guidance on that,
  • Erasing the ThemeProvider and/or withStyles keys are solving the problem, so at least I know there's a problem here. (and the error message on my main app is pointing towards a function directly in my module/node_modules, on a function using useContext() from material-ui)
  • Using MuiThemeProvider instead of ThemeProvider does not solve the problem
  • Using an earlier version of Material UI and/or ReactJS is a no-go in this case

The message itself is the infamous Invalid hook call from react

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 blabla for tips about how to debug and fix this problem.

As you can see here in the code :

  "devDependencies": {
    ...
    "webpack-cli": "^3.3.2",
    "webpack-dev-server": "^3.5.1",
    "sass-loader": "^7.1.0",
    "@material-ui/core": "^4.0.0",
    "style-loader": "^0.23.1"
  },
  "dependencies": {
    "babel-core": "^7.0.0-bridge.0",
    "prop-types": "^15.7.2"
  },
  "peerDependencies": {
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-proptypes": "^1.0.0",
    "@material-ui/core": "^4.0.0"
  }

I've put my dependencies as peers to avoid conflicts between React versions (and material ui too, but it seems to have little to none effects). I've truncate the devDependencies to avoid the full list here.

my rollup config :

export default {
  input: 'src/index.js',
  output: [{
    file: pkg.main,
    format: 'es'
  }],
  // All the used libs needs to be here
  external: [
    'react', 
    'react-dom',
    'react-proptypes',
    '@material-ui/core',
    '@material-ui/styles',
    'prop-types'
  ],
  plugins: [
    resolve({ preferBuiltins: false }),
    postcss({
      plugins: [
        postcssModules({
          getJSON (id, exportTokens) {
            cssExportMap[id] = exportTokens;
          }
        })
      ],
      getExportNamed: false,
      getExport (id) {
        return cssExportMap[id];
      },
      extract: 'dist/styles.css',
    }),
    json({
      'include': 'node_modules/**'
    }),
    babel({
      presets: ["@babel/preset-env", "@babel/preset-react"],
      plugins: ["@babel/plugin-proposal-class-properties",  "@babel/plugin-proposal-export-default-from"],
      exclude: [
        'node_modules/**'
      ],
    }),
    commonjs({
      include: 'node_modules/**',
      namedExports: {
        'node_modules/react-is/index.js': ['ForwardRef', 'isValidElementType']
      }
    })
  ]
}

and my code which if I suppress ThemeProvider I have no error on it :

import { render } from 'react-dom'
import React, { Component } from 'react'
import { MuiThemeProvider } from '@material-ui/core/styles'

const props = {}

class Boilerplate extends Component {
  render() {
    return (<div className='title'>Hello world</div>)
  }
}

render(<MuiThemeProvider><Boilerplate /></MuiThemeProvider>, document.getElementById('app'));

Any help that can solve this problem is really, really much appreciated !

1 Answers

For anyone wondering what was the problem, Yarn and NPM, even while listing react calls in the console, where not listing the react version used by the module linked. So I thought there was only one react version. Using PeerDependencies did not solve the problem either.

using https://github.com/facebook/react/issues/13991#issuecomment-496383268 I was able to use an Alias in my main app and it's solving the duplicate react call in the module.

Related