我已经构建了一个npm包,一个使用Vite及其库模式的可重用的ReactJS组件。它一直有效,直到一个多星期前,当我尝试运行本地开发服务器以通过 npm 符号链接添加一些新功能时。就在这时,它突然抛出了
Invalid hook call. Hooks can only be called inside of the body of a function component...
:
作为我使用的库的初始指南这篇文章。
错误中描述的问题
我做的第一件事是检查错误中描述的三个可能的原因。
阅读类似情况时出现问题的一般原因似乎是使用 npm 链接或符号链接。但即使删除它后,错误仍然存在。
检查早期的 git 版本
由于当前的 git 版本无法工作,我尝试查看早期版本。但开发工具仍然显示该版本的相同错误。
创建一个新的干净的Vite项目并安装我的npm包
我还创建了一个单独的新的干净的Vite项目,我在其中安装了npm包。它显示错误。
查看了帖子建议
我已经浏览了此问题
中链接的线程中的许多建议解决方案resolutions
标志添加到 package.jsonpeerDependencies
项目的主要部分是lib、src和dist文件夹。
💡因为我可以通过相对路径(来自lib文件夹)实现src文件夹中的组件,没有任何问题。 我最好的猜测是配置和 dist-folder 的某些内容导致了错误。
package.json
{
"name": "react-sheet-modal",
"private": false,
"version": "1.0.11",
"description": "An authentic modal sheet for ReactJs - Bringing the ()iOS experience to the web",
"repository": {
"url": "git+https://github.com/Colin-Farkas-Personal/React-Sheet-Modal.git"
},
"homepage": "https://github.com/Colin-Farkas-Personal/React-Sheet-Modal/blob/main/README.md",
"keywords": [
"ReactJs",
"sheet",
"modal"
],
"author": {
"name": "Colin Farkas",
"email": "[email protected]"
},
"type": "module",
"main": "dist/main.js",
"module": "dist/main.js",
"types": "dist/main.d.ts",
"files": [
"dist"
],
"sideEffects": [
"**/*.css"
],
"scripts": {
"dev": "vite",
"dev:app1": "vite --mode app_1",
"dev:app2": "vite --mode app_2",
"build": "tsc -b ./tsconfig.lib.json && vite build",
"build:watch": "tsc -b ./tsconfig.lib.json && vite build --watch",
"lint": "eslint .",
"preview": "vite preview",
"prepublishOnly": "npm run build"
},
"peerDependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
"@types/node": "^22.9.3",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.3",
"concurrently": "^9.1.0",
"eslint": "^9.13.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.13",
"globals": "^15.11.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"sass": "^1.83.0",
"typescript": "~5.6.2",
"typescript-eslint": "^8.10.0",
"vite": "^5.4.9",
"vite-plugin-dts": "^4.3.0",
"vite-plugin-lib-inject-css": "^2.1.1",
"vite-plugin-restart": "^0.4.2",
"vite-plugin-svgr": "^4.3.0"
}
}
vite.config.ts
import { resolve } from 'path';
import { defineConfig } from 'vite';
import dts from 'vite-plugin-dts';
import { libInjectCss } from 'vite-plugin-lib-inject-css';
import ViteRestart from 'vite-plugin-restart';
import svgr from 'vite-plugin-svgr';
export default defineConfig({
plugins: [
libInjectCss(),
dts({
tsconfigPath: resolve(__dirname, 'tsconfig.lib.json'),
}),
ViteRestart({
restart: ['/lib/**'],
}),
svgr({
svgrOptions: {
ref: true,
svgo: false,
titleProp: true,
},
include: '**/*.svg',
}),
],
build: {
copyPublicDir: false,
lib: {
entry: resolve(__dirname, 'lib/main.ts'),
formats: ['es'],
},
rollupOptions: {
output: {
assetFileNames: 'assets/[name][extname]',
entryFileNames: '[name].js',
},
external: ['react', 'react-dom'],
},
},
resolve: {
dedupe: ['react', 'react-dom'],
},
});
tsconfig.app.json
{
"compilerOptions": {
"target": "ES6",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,
"types": ["vite/client"]
},
"include": ["src", "env.ts", "src/vite-env.d.ts"]
}
tsconfig.lib.json
{
"extends": "./tsconfig.app.json",
"include": ["lib"],
"exclude": ["src"]
}
我能够通过确保没有react/jsx-runtime实例被导入或捆绑到转译代码中来修复这个错误。
问题是 main.js 文件(在 dist 文件夹内)包含了 React/jsx-runtime,这会导致重复的 React 导出对象,因为开发环境也在使用 React。
我更新了 vite.config.ts 中的 rollupOptions 以正确排除 React/jsx-runtime 代码:
export default defineConfig({
{ ... }
build: {
copyPublicDir: false,
lib: {
entry: resolve(__dirname, './lib/main.ts'),
formats: ['es'],
},
rollupOptions: {
external: ['react', 'react/jsx-runtime'],
output: {
assetFileNames: 'assets/[name][extname]',
entryFileNames: '[name].js',
},
},
},
});