5

问题描述:

  • 我目前正在创作一个名为eformless

  • 我使用CRA创建了一个名为 的目录sandbox,我在其中链接了包。

  • 在尝试使用我正在尝试测试的链接包启动沙盒反应应用程序时,我不断收到以下错误:

    // inside my 'sandbox' App.tsx
    import React from 'react'
    import { useField } from 'eformless'
    
    const App = () => {
      const [test, handleChange] = useField('testing')
      return (
        <input type="text" value={test.value} onChange={handleChange} />
      )
    }
    

错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。这可能由于以下原因之一而发生:

  1. 你可能有不匹配的 React 版本和渲染器(例如 React DOM)
  2. 您可能违反了 Hooks 规则
  3. 您可能在同一个应用程序中拥有多个 React 副本请参阅由于 stackoverflow ToS 导致的更改链接,以获取有关如何调试和修复此问题的提示。

出现问题的地方:

这个问题似乎指向我的库,在那里我编写了一个自定义钩子,它使用从 React 导入的钩子。
这是我的代码中有问题的摘录:

export const useField = <T>(
  input: T
  ...checkFunctions: Array<(...args: unknown[]) => unknown>
): [FieldType<T>, FieldHandlerFunction<T>, FieldHandlerFunction<T>] => {
  const [value, setValue] = useState(input)
  const [name, setName] = useState('')
  // Issue seems to be here ^
}

我的设置相当正常,似乎在其他项目中运行良好:

  • 首先我通过捆绑我的图书馆rollup -c
  • eformless通过在我的库文件夹中创建一个链接npm link
  • 并通过在我的sandbox文件夹中创建符号链接npm link eformless

我尝试了什么:

我自然地尝试通过错误消息中提供的链接解决问题。链接您自己的库时,这似乎是一个问题,如此处所述

当您使用 npm link 或等效项时,也会出现此问题。在这种情况下,你的打包器可能会“看到”两个 React——一个在应用程序文件夹中,一个在你的库文件夹中。假设 myapp 和 mylib 是同级文件夹,一种可能的解决方法是从 mylib 运行 npm link ../myapp/node_modules/react。这应该使库使用应用程序的 React 副本。

我确实npm link ../sandbox/node_modules/react在我的eformless文件夹中运行了,但这似乎没有帮助,即使在关闭节点服务器并重新编译之后也是如此。

无论哪种方式,我都觉得很困惑,因为 runnignnpm ls react只显示一个版本的 react 并且它应该是有效的,因为在useState自定义钩子中使用了顶层。

重现问题

两个存储库都是公开的

4

3 回答 3

6
  1. 您可能在同一个应用程序中拥有多个 React 副本请参阅由于 stackoverflow ToS 导致的更改链接,以获取有关如何调试和修复此问题的提示。

这是因为你在你devDependencies的无形中做出了反应。这会导致您的应用程序运行两个 React 实例。

相反,将 react 移至 eformless 中的对等依赖项package.json,删除您的node_modules目录并运行npm install.

通过添加对对等依赖项的反应,您通知您的模块捆绑器不要包含反应,而是期望反应将由依赖的应用程序提供给它。

"peerDependencies": {
  "react": "^16.13.1"
}

另外,我注意到您已将node_modules目录签入 eformless。你不应该那样做。相反,添加node_modules到您的.gitignore文件中。

于 2020-10-09T16:49:07.007 回答
5

以防万一它对其他人有用,我已经在我的库中使用 react 作为“对等依赖项”,但仍然遇到这个问题。

我必须执行以下步骤来解决它:

在图书馆

  1. 如果您还没有这样做,请将产生问题的库设置为peerDependencies代替package.jsondependenciesdevDependencies例如在我的情况下react
"peerDependencies": {
  "react": "^16.8.6",
  ...
}
  1. npm install
  2. 构建库(在我的例子中,使用rollup -cnpm 脚本)

在我的主应用程序中

  1. 更改我的库的版本以指向具有相对路径的本地项目package.json,例如
"dependencies": {
  "my-library": "file:../../libraries/my-library",
  ...
}
  1. 添加resolve.symlinks = false到我的主应用程序的 webpack 配置中

  2. --preserve-symlinks-main将and添加--preserve-symlinks到我的package.json启动脚本中,例如:

"scripts": {
  "build": "set WEBPACK_CONFIG_FILE=all&& webpack",
  "start": "set WEBPACK_CONFIG_FILE=all&& webpack && node --preserve-symlinks-main --preserve-symlinks dist/server.js",
}
  1. npm install
  2. npm run start
于 2021-06-22T18:52:20.210 回答
1

另一种选择是在依赖应用程序的构建中使用 webpackalias来对反应依赖项进行重复数据删除。

webpack.config.js应用程序消费链接依赖项内部:

resolve: {
  alias: {
    react: path.resolve(__dirname, '<app_path>/node_modules/react'),
    'react-dom': path.resolve(__dirname, '<app_path>/node_modules/react-dom')
  }
}
于 2021-09-19T21:49:03.023 回答