You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从TS React组件库导入带Hook组件时触发无效Hook调用错误

解决React组件库导入后Hook调用错误的问题

出现Invalid hook call. Hooks can only be called inside of the body of a function component.错误,且仅含Hook的组件报错、纯文本组件正常,核心原因几乎都是项目中存在多个React实例——你的组件库构建时打包了自己的React,而宿主应用又加载了另一份,导致Hook检测到的React环境不匹配。

以下是具体解决步骤:

1. 把React设为组件库的peer依赖

组件库不需要自己打包React,而是依赖宿主项目提供的React版本。修改组件库的package.json:

{
  "peerDependencies": {
    "react": "^17.0.0 || ^18.0.0",
    "react-dom": "^17.0.0 || ^18.0.0"
  },
  "devDependencies": {
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  }
}
  • peerDependencies声明组件库兼容的React版本,宿主安装时会提示是否满足依赖;
  • devDependencies保留React用于组件库本地开发、测试。

2. 配置构建工具排除React

针对Rollup

修改rollup.config.js,将React和ReactDOM设为外部依赖,不打包进产物:

export default {
  input: 'src/index.ts',
  external: ['react', 'react-dom'], // 排除这两个包
  output: {
    file: 'dist/index.js',
    format: 'esm',
    globals: { // 全局变量映射,用于UMD格式
      react: 'React',
      'react-dom': 'ReactDOM'
    }
  },
  // ...其他插件配置(如@rollup/plugin-typescript等)
}

针对TSC

修改tsconfig.json,确保编译时不处理React依赖:

{
  "compilerOptions": {
    "module": "ESNext",
    "target": "ES2015",
    "declaration": true,
    "outDir": "./dist",
    "skipLibCheck": true // 跳过库类型检查,避免版本冲突
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

同时在组件库package.json中指定正确的入口字段:

{
  "main": "dist/index.js",
  "module": "dist/index.js",
  "types": "dist/index.d.ts"
}

3. 修复导入不匹配的问题

你的组件库用了export default HelloWorld,但宿主项目用了命名导入import { HelloWorld } from 'component-library-starter',这会导致导入的是undefined,可能间接引发错误。

方案一:修改宿主项目的导入语句:

import React from 'react';
import HelloWorld from 'component-library-starter'; // 改为default导入

function App() {
  return (
    <div className="App">
      <HelloWorld />
    </div>
  );
}

方案二:组件库改为命名导出:

import React from "react";

export const HelloWorld: React.FC = () => {
  const [counter, setCounter] = React.useState(0);
  return (
    <div>
      {counter}
      <button onClick={() => setCounter(counter + 1)}>+</button>
      <button onClick={() => setCounter(counter - 1)}>-</button>
    </div>
  );
};

4. 本地调试避免多实例

如果是本地通过npm link调试组件库,宿主项目可能会加载组件库node_modules里的React,导致多实例。解决办法:

  • 在宿主项目中执行:npm link ../component-library/node_modules/react,让宿主共享组件库的React;
  • 或者用yalc替代npm link,更稳妥地管理本地包依赖。

内容的提问来源于stack exchange,提问作者Layan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 01:04:59