我正在编写一个名为“Formcomponent”的包,使用React + React Bootstrap。
这是index.tsx
/**
* Renders a component for a form.
*/
import React from "react";
import Form from "react-bootstrap/Form";
/**
* List of props
* @returns
*/
interface FormcomponentProps {
name: string;
}
export const Formcomponent = ({ name }: FormcomponentProps) => {
return (
<Form.Group controlId={name}>
{/* input text */}
<Form.Label>{name}</Form.Label>
<Form.Control type="text" name={name} />
</Form.Group>
);
};
当我构建它时,我得到了dist:index.d.ts
/**
* Renders a component for a form.
*/
import React from "react";
/**
* List of props
* @returns
*/
interface FormcomponentProps {
name: string;
}
export declare const Formcomponent: ({ name }: FormcomponentProps) => React.JSX.Element;
export {};
和index.js
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Formcomponent = void 0;
/**
* Renders a component for a form.
*/
var react_1 = __importDefault(require("react"));
var Form_1 = __importDefault(require("react-bootstrap/Form"));
var Formcomponent = function (_a) {
var name = _a.name;
return (react_1.default.createElement(Form_1.default.Group, { controlId: name },
react_1.default.createElement(Form_1.default.Label, null, name),
react_1.default.createElement(Form_1.default.Control, { type: "text", name: name })));
};
exports.Formcomponent = Formcomponent;
我在package.json中导入另一个React项目作为"@sineverba/form-component": "file:../../personali/npm-pkg-form-component",
,在React项目的App.jsx中使用它作为
import * as React from "react";
import { Form } from "react-bootstrap";
import { Formcomponent } from "@sineverba/form-component";
export const App = () => {
return (
<Form>
<Formcomponent name="ciao" />
</Form>
);
};
export default App;
但我进了控制台
Warning: 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: [...]
和
Uncaught TypeError: Cannot read properties of null (reading 'useMemo') at FormGroup.js:11:26
(来自react bootstrap的FormGroup.js定义为:
import * as React from 'react';
import { useMemo } from 'react';
import FormContext from './FormContext';
import { jsx as _jsx } from "react/jsx-runtime";
const FormGroup = /*#__PURE__*/React.forwardRef(({
controlId,
// Need to define the default "as" during prop destructuring to be compatible with styled-components github.com/react-bootstrap/react-bootstrap/issues/3595
as: Component = 'div',
...props
}, ref) => {
const context = useMemo(() => ({
controlId
}), [controlId]);
return /*#__PURE__*/_jsx(FormContext.Provider, {
value: context,
children: /*#__PURE__*/_jsx(Component, {
...props,
ref: ref
})
});
});
FormGroup.displayName = 'FormGroup';
export default FormGroup;
更新1
在index.tsx(外部组件)中,我将React导入为import * as React from "react";
,但得到了相同的错误。
更新2
我在这里上传了repository:https://github.com/sineverba/npm-pkg-form-component
当然它没有发布(是的),为了测试它可以在本地克隆并与"@sineverba/form-component": "file:../../personali/npm-pkg-form-component"
一起使用
一个小消息。我试图导出一个简单的<p>Hello World</p>
(一个简单的HTML),只有当我使用Formcomponent
而不是FormComponent
作为名称时,它才能工作(请参阅C
的大写字母)。
顺便说一下,将名称更改为Formcomponent
并引入React Bootstrap Form,也会出现同样的错误。
更新3
我从我的组件中导出了一个简单的input
标记,它可以工作。可能是从另一个组件导入的React Bootstrap库的一些奇怪错误。
4条答案
按热度按时间gajydyqb1#
首先检查React项目和
Formcomponent
库是否使用了React和React Bootstrap的兼容版本。不匹配的版本可能会导致像Invalid hook call
这样的错误。在你的项目中,查看
package.json
文件以找到你正在使用的React版本。它将列在dependencies
部分下,例如,类似地,在
Formcomponent
包中,查看其package.json
文件以查找它使用的React版本,例如,比较版本号以查看它们是否匹配。如果存在差异,可能会导致问题。
在
Formcomponent
包中将React
和React Bootstrap
Decrypt为peer dependencies,以避免重复安装。这告诉你的库的消费者他们应该使用哪个版本的React和React Bootstrap,而不需要将它们包含在你的库包中。您还可以运行
npm ls react
或yarn list react
命令(取决于您使用的是npm还是yarn)。此命令将列出项目中所有已安装的React版本以及它们的使用位置。
注意:项目中
Formcomponent
的import语句与Formcomponent
包中的export语句不匹配。import语句是import { Formcomponent } from "@sineverba/form-component";
,但在你的项目中,你试图将它用作<FormComponent name="ciao" />
,而应该是<Formcomponent name="ciao" />
(区分大小写)。在开发过程中,考虑使用
npm link
或yarn link
链接到本地Formcomponent
包,而不是使用package.json
中的文件路径。这将允许您在更真实的环境中测试库,类似于发布时的使用方式。我从我的组件中导出了一个简单的
input
标记,它可以工作。可能是从另一个组件导入的React Bootstrap库的一些奇怪错误。
如果导出一个简单的HTML
input
标签可以工作,但从React Bootstrap导出一个组件却不行,这表明React Bootstrap在Formcomponent
包中的使用或集成可能存在问题。如果React Bootstrap还没有在
Formcomponent
包中声明为对等依赖,那么这样做会很好。这样,Formcomponent
将使用安装在消费项目中的React Bootstrap版本,这有助于避免版本冲突和重复依赖。并确保React Bootstrap组件在
Formcomponent
包中正确导入。仔细检查import语句,并将其与React Bootstrap的文档进行比较,以确保准确性。查看控制台中提供的特定错误消息和堆栈跟踪,以查明错误的来源。这可以提供一些线索,说明使用React Bootstrap组件时会出现什么问题。
yv5phkfx2#
在您的Formcomponent.tsx中,从react-bootstrap导入Form和FormLabel并相应地使用它们:
tsx:
zhte4eai3#
当我创建一个包并尝试使用它时,我曾经像你一样遇到过这个问题。这是因为
react
声明在package.json中,你需要把它放在Formcomponent
中的peerDependencies
中,而不是dependencies
或devDependencies
package.json中。是因为你将有另一个副本的React在您的应用程序中,导致errorz0qdvdin4#
这与项目加载两个React示例有关。
虽然目前大多数其他答案似乎都归咎于版本不匹配,但我认为这实际上是软件包解析的问题。
假设你正在观看两个不同的版本:
1.项目-这是你的入口点应用程序。
1.表单库-这是您在本地创建的可重用包。
这两个构建都将具有“/node_modules/react”。
当在package.json中使用“file:“来安装一个包时,它会在node_modules中创建一个链接,指向包的原始位置(开发位置)(Form Library)。
这意味着当您的项目构建解析包时,它将找到表单库的node_modules文件夹,并将其用作其包解析的一部分。
在解析包时,优先级顺序为:别名>本地节点模块>根节点模块。
这对你的项目意味着什么,当它为位于你的表单库中的文件解析包时,它将从“表单库/节点模块”中解析,如果它没有找到包,它将检查“项目/节点模块”。
这就是给你两个版本的React的原因:
如果你使用任何捆绑的包分析器,你应该能够看到两个React示例被包括在内。
为了解决这个问题,你可以同时开发你的Project和Form Library,你可以在你的构建中添加一个别名,并强制它将React解析为Project/node_modules/react。
Webpack别名-https://webpack.js.org/configuration/resolve/#resolvealias
ViteJs别名-https://vitejs.dev/config/shared-options.html#resolve-alias
注意:任何共享的、具有单例或类似的包都需要别名,以避免问题。
ViteJs Super Heavy Handed Example -项目配置: