尝试创建可共享的 React 组件 - 但无法导入它

Trying to create a shareable React component - but failing to import it

我正在尝试分享我通过本地托管的 npm 存储库创建的 React 组件。

为此,我使用打字稿创建了 React 组件,将其转换为 js 并将生成的代码发布到 repo。但是当我在现有项目(一个带有 typescript 的基本 create-react-app 项目)中安装这个包并尝试使用该组件时 - 我的应用程序试图编译它几分钟但我未能加载该组件。有时,如果我等待几分钟,我会看到此错误 - 虽然该组件已经过测试并且可以正常工作:

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.'

我复制了相同的组件以嵌入到应用程序中,而不是通过 npm 安装 - 它有效。我试图将组件剥离到最低限度 - 它仍然需要很长时间。

重现步骤很简单:

我在 github 中分享了组件:

https://github.com/ymoran00/example-Whosebug-react

要构建它,您需要 运行 npm install 然后 npm 运行 build。 结果将在 lib 文件夹中生成。 然后你可以进入 lib 文件夹和 运行:

npm link

然后新建一个 typescript create-react-app 项目:

npx create-react-app my-app --template typescript

进去然后运行:

npm link login-component

这将安装链接包。

现在转到 App.tsx 并导入包:

import LoginContainer from 'login-component/LoginContainer';

并在应用程序中使用它:

<LoginContainer onLogin={()=> {alert('success')}}/>

运行 带有 npm start 的应用程序。

应用程序将打开浏览器 - 但不会加载任何内容。它有点卡在构建或其他什么东西上——我不知道那里发生了什么。如果您查看该组件,您会发现它是一个非常基本的组件 Material-UI.

我首先查看的是您的 package.json 文件,因为您很可能正在处理原因 #1:

You might have mismatching versions of React and the renderer (such as React DOM)

我看到您将 reactreact-dom 作为组件的依赖项。您应该将它们从 dependencies 移至 peerDepenedencies。您可能还想将 @material-ui/core@material-ui/icons 移动到 peerDependencies。现在 React 与你的组件捆绑在一起,你的组件使用它自己的 React 版本,而不是你应用程序中的版本。您希望使用您的组件的项目能够独立包含 React。

有关为什么要使用 peerDependencies 的更多信息,请参阅此问题:

  • What's the difference between dependencies, devDependencies and peerDependencies in npm package.json file?

我在这个过程中遇到的主要问题似乎是使用npm link。 与钩子结合使用时会导致问题 - 这就是我收到此钩子错误的原因。 另请参阅此线程:

https://github.com/facebook/react/issues/13991

所以我没有使用 npm link,而是开始使用 npm-sync,它似乎解决了问题。