Webpacked React组件在发布到NPM并在另一个模块中导入时不可用



我已经仔细阅读了与我的问题相关的帖子,但我仍然无法将我的react组件正确导入到另一个项目中。我有一个半非平凡的react组件,它使用react钩子显示网格(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;

这是为网页设计的。这是webpack-config:

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复制到一个文件夹中,该文件夹包含一个最小的package.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"
}
}

我在webpack配置中尝试过更改库和libraryTarget,结果各不相同。我尝试使用Rollup,但由于MaterialTable的问题,导致了不同的错误。

如果没有人有任何想法可以帮助我,我会把它发布在github上,这样就有了更具体的东西可以玩。

我遇到的问题是在发布es6模块时对webpack的已知限制。有很多文章描述了解决方法,但到目前为止,我还没有找到任何适合我的方法。然而,我发现使用Rollup是一种可以让webpack发挥作用的替代方案,我终于能够通过遵循github存储库中的代码来发布和重用我的react组件。我还没有更新我的样本回购中的代码,但也许我会重新开始,但我已经忙于这个问题好几天了,是时候继续了。

最新更新