Webpacked React компонент не может использоваться при публикации в NPM и импортировании в другой модуль - PullRequest
0 голосов
/ 20 марта 2020

Я просматривал сообщения, связанные с моим вопросом, но я все еще не могу заставить мой компонент реагировать правильно импортировать в другой проект. У меня есть полу-нетривиальный компонент реакции, который отображает сетку (MaterialTable), используя реагирующие крючки. Он хорошо работает при импорте напрямую из того же проекта, который его реализует. Проблема возникает, когда после публикации в NPM и импорта его в другой проект:

react-dom.development.js?7f13:11125 Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component.

Вот компонент:

import React, { useContext, createContext, useState, forwardRef } from 'react';
import MaterialTable from 'material-table';
import Button from '@material-ui/core/Button';

const QbsContext = createContext();

import AddBox from '@material-ui/icons/AddBox';
import ArrowDownward from '@material-ui/icons/ArrowDownward';
import Check from '@material-ui/icons/Check';
import ChevronLeft from '@material-ui/icons/ChevronLeft';
import ChevronRight from '@material-ui/icons/ChevronRight';
import Clear from '@material-ui/icons/Clear';
import DeleteOutline from '@material-ui/icons/DeleteOutline';
import Edit from '@material-ui/icons/Edit';
import FilterList from '@material-ui/icons/FilterList';
import FirstPage from '@material-ui/icons/FirstPage';
import LastPage from '@material-ui/icons/LastPage';
import Remove from '@material-ui/icons/Remove';
import SaveAlt from '@material-ui/icons/SaveAlt';
import Search from '@material-ui/icons/Search';
import ViewColumn from '@material-ui/icons/ViewColumn';

const tableIcons = {
  Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />),
  Check: forwardRef((props, ref) => <Check {...props} ref={ref} />),
  Clear: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
  Delete: forwardRef((props, ref) => <DeleteOutline {...props} ref={ref} />),
  DetailPanel: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
  Edit: forwardRef((props, ref) => <Edit {...props} ref={ref} />),
  Export: forwardRef((props, ref) => <SaveAlt {...props} ref={ref} />),
  Filter: forwardRef((props, ref) => <FilterList {...props} ref={ref} />),
  FirstPage: forwardRef((props, ref) => <FirstPage {...props} ref={ref} />),
  LastPage: forwardRef((props, ref) => <LastPage {...props} ref={ref} />),
  NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
  PreviousPage: forwardRef((props, ref) => <ChevronLeft {...props} ref={ref} />),
  ResetSearch: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
  Search: forwardRef((props, ref) => <Search {...props} ref={ref} />),
  SortArrow: forwardRef((props, ref) => <ArrowDownward {...props} ref={ref} />),
  ThirdStateCheck: forwardRef((props, ref) => <Remove {...props} ref={ref} />),
  ViewColumn: forwardRef((props, ref) => <ViewColumn {...props} ref={ref} />)
};

const qbsColumns = [
  { title: "First Name", field: "name" },
  { title: "Last Name", field: "surname" },
  { title: "Year of Birth", field: "birthYear", type: "numeric" },
  {
    title: "City of Birth",
    field: "birthCity",
    lookup: {
      34: 'Haughton',
      63: 'San Diego',
      88: 'Henryetta',
      90: 'Mount Vernon',
      91: 'Chicago',
      92: 'Dallas',
      93: 'Campbell',
      94: 'Cincinatti',
      95: 'Mesa',
      89: 'San Rafael'
    }
  }
];

const qbData = [
  { name: "Dak", surname: "Prescott", birthYear: 1993, birthCity: 34 }
];

const addData = [
  { name: "Danny", surname: "White", birthYear: 1952, birthCity: 95 },
  { name: "Roger", surname: "Staubach", birthYear: 1942, birthCity: 94 },
  { name: "Jerry", surname: "Rhome", birthYear: 1942, birthCity: 92 },
  { name: "Craig", surname: "Morton", birthYear: 1943, birthCity: 93 },
  { name: "John", surname: "Roach", birthYear: 1933, birthCity: 92 },
  { name: "Don", surname: "Heinrich", birthYear: 1948, birthCity: 91 },
  { name: "Don", surname: "Meredith", birthYear: 1938, birthCity: 90 },
  { name: "Edward", surname: "LeBaron", birthYear: 1930, birthCity: 89 },
  { name: "Troy", surname: "Aikman", birthYear: 1966, birthCity: 88 },
  { name: "Tony", surname: "Romo", birthYear: 1980, birthCity: 63 }
];

let qbIndex = 0;

const QbsComponent = () => {
  const { qbs, addRow } = useContext(QbsContext);

  return (
    <div>
      <MaterialTable
        icons={tableIcons}
        columns={qbsColumns}
        data={qbs}
        title="Dallas Cowboys Quarterbacks"
      />

      <Button onClick={() => addRow()}>Add Row</Button>
    </div>
  )
};

const Qbs = () => {
  const [qbs, setQbs] = useState(qbData);

  const addRow = () => {
    setQbs([...qbs, addData[qbIndex++]]);
  };

  return (
    <div>
      <QbsContext.Provider value={{ qbs, addRow }}>
        <QbsComponent />
      </QbsContext.Provider>
    </div>
  );
};

export default Qbs;

Это предназначено для веб-страницы. Это конфиг веб-пакета:

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
   // Entry points that have the 'babel-polyfill' value do so in order to use
   // async/await
   entry: {
      'qbs': ['idempotent-babel-polyfill', './src/main/web/app/index.js'],
      'app': ['idempotent-babel-polyfill', './src/main/web/index.js']
   },

   devtool: 'sourcemaps',

   cache: true,

   mode: 'development',

   output: {
      path: path.resolve(__dirname + '/target/classes/static/'),
      filename: '[name].js',
      libraryTarget: 'commonjs-module'
   },

   module: {
      rules: [
         {
            test: /\.css$/,
            use: [
               'style-loader',
               'css-loader'
            ]
         },

         { test: /\.woff$/, use: 'url-loader?prefix=font/&limit=5000&mimetype=application/font-woff' },
         { test: /\.woff2$/, use: 'url-loader?prefix=font/&limit=5000&mimetype=application/font-woff2' },
         { test: /\.ttf$/, use: 'file-loader?prefix=font/' },
         { test: /\.eot$/, use: 'file-loader?prefix=font/' },
         { test: /\.svg$/, use: 'file-loader?prefix=font/' },
         { test: /\.(png|jpe?g|gif)$/i, use: [{loader: 'file-loader'}] },
         {
            test: /\.js$/,
            exclude: /(node_modules)/,
            use: [{
               loader: 'babel-loader',
               options: {
                  presets: [
                     '@babel/preset-env', {
                        plugins: [
                           '@babel/plugin-proposal-class-properties'
                        ]
                     },
                     '@babel/preset-react'
                  ],
                  plugins: [
                     [
                        '@babel/plugin-proposal-decorators', { 'legacy': true }
                     ]
                  ]
               }
            }]
         }
      ]
   },

   resolve: {
       alias: {
          'react-dom': '@hot-loader/react-dom'
       }
   },

   plugins: [
      new MiniCssExtractPlugin()
   ]
};

Я копирую получившиеся qbs. js в папку с минимальным пакетом. json:

{
   "name": "@sellis/qbs",
   "version": "1.0.0",
   "main": "qbs.js",
   "module": "qbs.js",
   "publishConfig": {
      "access": "public"
   },
   "peerDependencies": {
      "react": "^16.12.0",
      "react-dom": "^16.12.0"
   }
}

Я играл вокруг с изменением библиотеки и библиотеки цели в конфигурации веб-пакета, и результаты изменились. Вместо этого я попытался использовать Rollup, и это привело к различным ошибкам из-за проблем с MaterialTable.

Если ни у кого нет идей, которые могут мне помочь с этим, я выложу это на github, чтобы было что-то более осязаемое для поиграй с.

1 Ответ

0 голосов
/ 24 марта 2020

Проблема, с которой я столкнулся - это известное ограничение для веб-пакетов при публикации модулей es6. Есть много статей, описывающих обходные пути, но до сих пор я не заставил ни одну из них работать на меня. Однако я обнаружил, что использование Rollup является альтернативой веб-пакету, который можно заставить работать, и я наконец смог опубликовать sh и повторно использовать свой компонент реагирования, следуя коду в этом репозитории github . Я не обновлял код в моем примере репозитория, но, возможно, я вернусь к нему, но я был так занят этой проблемой уже пару дней, и пришло время двигаться дальше.

...