Categories
Mastering Development

React hooks widget works when used directly but not when imported from NPM

I have a moderately simple example of a React Hooks widget whose function it is to provide context hooks to provide state that can set a few strings and switch the current Material UI theme. Here is the working demo. By clicking on the button labeled “NEXT THEME” you can see the page toggle between yellow and blue, along with some text changes indicating the name of the theme.

Its a contrived example, but the idea is that at the top of my site, I’m wrapping all content with context providers so that any nested widget can access shared state. Looks like this:

import React from "react";

import { AppContext } from "./AppContext";
import { ThemeContextProvider } from "./ThemeContext";

export default function App(props) {
  return (
    <div>
      <ThemeContextProvider>
        <AppContext>{props.children}</AppContext>
      </ThemeContextProvider>
    </div>
  );
}

Everything is working as I said in the demo I’ve linked above. But when I publish this code to NPM and then use it in another project, it mostly works except for one import piece–the theme color will not change. All other state changes work right–all of the other state changes are textual and there are no problems, but the color will not change.

The theme is provided by Material UI, and I suspect that there is an issue with the way that I am rolling all this code up for publishing to NPM. I am using Rollup–here is rollup.config.js:

import babel from 'rollup-plugin-babel';
import commonjs from 'rollup-plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import resolve from 'rollup-plugin-node-resolve';
import json from '@rollup/plugin-json';
const {terser} = require('rollup-plugin-terser');

import pkg from './package.json';

export default {
  input: 'src/index.js',
  output: [
    {
      file: pkg.main,
      format: 'cjs',
      sourcemap: true
    },
    {
      file: pkg.module,
      format: 'es',
      sourcemap: true
    }
  ],
  plugins: [
    external(),
    // url({ exclude: ['**/*.svg'] }),
    babel({
      exclude: 'node_modules/**',
      runtimeHelpers: true
    }),
    resolve({
      preferBuiltins: true,
      browser: true
    }),
    commonjs({
      include: 'node_modules/**',
      browser: true,
      namedExports: {
        'node_modules/react/index.js': [
          'createContext',
          'useContext',
          'useEffect',
          'useState'
        ],
        'node_modules/react-is/index.js': [
          'ForwardRef',
          'Memo'
        ],
        'node_modules/prop-types/index.js': [
          'elementType'
        ]
      }
    }),
    terser(),
    json()
  ]
};

And here is my package.json:

{
  "name": "@data-factory/theme-context-test",
  "version": "0.0.1",
  "description": "Code from CodeSandbox",
  "author": "sellis42",
  "main": "dist/index.js",
  "module": "dist/index.es.js",
  "jsnext:main": "dist/index.es.js",
  "engines": {
    "node": ">=8",
    "npm": ">=5"
  },
  "publishConfig": {
    "access": "public"
  },
  "scripts": {
    "build": "rollup -c",
    "start": "rollup -c -w",
    "prepare": "npm run build",
    "predeploy": "cd example && npm install && npm run build"
  },
  "peerDependencies": {
    "react": "^16.12.0",
    "react-dom": "^16.12.0"
  },
  "devDependencies": {
    "@babel/core": "^7.9.0",
    "@babel/plugin-transform-runtime": "^7.9.0",
    "@babel/preset-env": "^7.9.0",
    "@babel/preset-react": "^7.0.0",
    "@babel/runtime": "^7.9.2",
    "@material-ui/core": "^4.9.8",
    "@material-ui/icons": "^4.9.1",
    "@material-ui/styles": "^4.9.6",
    "@rollup/plugin-json": "^4.0.2",
    "cross-env": "^5.2.0",
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-scripts": "^3.4.0",
    "rollup": "^1.32.1",
    "rollup-plugin-babel": "^4.4.0",
    "rollup-plugin-commonjs": "^9.3.4",
    "rollup-plugin-node-resolve": "^4.2.4",
    "rollup-plugin-peer-deps-external": "^2.2.2",
    "rollup-plugin-terser": "^4.0.4",
    "typeface-roboto": "0.0.75"
  }
}

I feel as if there is something missing from my rollup configuration. This project is on my local development system and is slightly different that the linked code. I essentially have all the code that I publish in the root of the widget module, and an example folder that demonstrates how to use the widget. I use npm link so that the example widget can use it, and that is where I see the issue I’m trying to resolve. I can copy the entire root widget to a subfolder of the example src and import it from there instead of from NPM and it works again.

Any help or ideas would be appreciated. I can put all of my code to Git if anyone is interested in taking a deeper look.

Leave a Reply

Your email address will not be published. Required fields are marked *