在发布为 npm 包之前使用 npm 链接测试组件时出现重复的 ReactJS 导入问题

IT技术 javascript reactjs npm webpack
2021-04-24 10:30:50

我有一个像这样的简单组件。

import React, {useState} from 'react';

function MyComponentWithState(props) {
    const [value, setValue] = useState(0);

    return (
        <p>My value is: {value}</p>
    ) 
}

export default MyComponentWithState;

我想将它作为单独的包发布在 NPM 上。所以,为此我准备了package.jsonwebpack.config.js,如下所示。

包.json:

{
  "name": "try-to-publish",
  "version": "0.0.1",
  "description": "Just a test",
  "main": "build/index.js",
  "scripts": {
    "start": "webpack --watch",
    "build": "webpack"
  },
  "author": {
    "name": "Behnam Azimi"
  },
  "license": "ISC",
  "peerDependencies": {
    "react": "16.9.0",
    "react-dom": "16.9.0"
  },
  "dependencies": {
    "react": "16.9.0",
    "react-dom": "16.9.0",
    "prop-types": "15.7.2",
    "react-scripts": "3.1.1",
    "webpack": "4.39.3"
  },
  "devDependencies": {
    "@babel/core": "7.6.0",
    "@babel/plugin-proposal-class-properties": "7.5.5",
    "@babel/preset-env": "7.6.0",
    "@babel/preset-react": "7.0.0",
    "babel-loader": "8.0.6",
    "babel-plugin-transform-object-rest-spread": "6.26.0",
    "babel-plugin-transform-react-jsx": "6.24.1",
    "css-loader": "3.2.0",
    "node-sass": "4.12.0",
    "sass-loader": "8.0.0",
    "style-loader": "1.0.0",
    "webpack-cli": "3.3.8",
    "webpack-external-react": "^1.1.2"
  }
}

webpack.config.json:

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'index.js',
        libraryTarget: 'commonjs2'
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                include: path.resolve(__dirname, 'src'),
                use: {
                    loader: "babel-loader"
                }
            },
        ]
    },
    resolve: {
        alias: {
            'react': path.resolve(__dirname, 'node_modules/react'),
            'react-dom': path.resolve(__dirname, 'node_modules/react-dom'),
        }
    },
    externals: {
        'react': "commonjs react",
        'react-dom': "commonjs react-dom"
    },
};

这是我的.babelrc:

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ],
  "plugins": ["@babel/plugin-proposal-class-properties"]
}

当我将组件发布到 NPM 并使用 `npm install 将其安装在我的另一个 ReactJs 项目中时,这些配置就像魅力一样工作,但我的重点是本地测试!

我想在发布之前测试这个组件/库。为此,我使用npm link功能将我的组件与我的主要 ReactJS 项目链接起来。

正如你在上面看到的,我的组件是功能性的,我也使用了钩子。因此,当我将本地链接的 lib 注入到我的主要 ReactJs 项目时,会遇到此错误,

无效的钩子调用。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一而发生的: 1. 你的 React 和渲染器的版本可能不匹配(例如 React DOM) 2. 你可能违反了 Hooks 规则 3. 你可能有多个 React 副本同一个应用

我的问题与 3td 原因有关。我的项目使用 ReactJs 并导入一次,我的组件也将导入 React!我的意思是在一个项目中两次 React 导入!.

我也有外部组件的配置有关react,并react-dom在我的WebPack配置。

我该怎么做才能解决这个问题?我的错误在哪里?

更新: 我也试过@sung-m-kim 和@eddie-cooro 所说的,但没有奏效!意思是,我改变的package.json和删除react,并react-domdependencies并将它们添加到devDpendencies

4个回答

我终于通过这些步骤解决了这个问题。

里面运行npm 链接

<your-library-package>/node_modules/react

里面运行npm 链接

<your-library-package>/node_modules/react-dom

然后在您的应用程序根目录中运行npm link reactnpm link react-dom

并且不要忘记将 react 和 react-dom 作为库中的外部对象

// webpack.config.js

const externals = {
    "react": "react",
    "react-dom": "react-dom",
}

module.exports = {
    .
    .
    .

   externals
   }

仅在package.json部分设置reactreact-nativepeerDependencies,而不是dependencies. 同样对于本地开发(当您的包未包含在任何其他 React 项目中并且您希望在本地运行时),您可以使用该devDependencies字段。

我在typescriptreact项目中解决了这个问题。

或许,使用时npm link采用react从主应用程序的项目及组件项目。

所以,在你package.json删除reactdependencies和/或devDependencies

检查答案:https : //stackoverflow.com/a/62807950/5183591

我解决了我的问题。我使用RollupJS而不是Webpack作为捆绑工具进行捆绑。

这是我的rollup.config.js

import {uglify} from 'rollup-plugin-uglify'
import babel from 'rollup-plugin-babel'

export default {
    input: "./src/index.js",
    external: ['react', 'react-dom'],
    output: {
        name: 'test-lib',
        format: "cjs",
    },
    plugins: [
        babel({
            exclude: "node_modules/**"
        }),
        uglify(),
    ],
};

和我的package.json

{
  "name": "test-lib",
  "version": "1.0.0",
  "main": "dist/test-lib.min.js",
  "scripts": {
    "build": "rollup -c -o dist/test-lib.min.js"
  },
  "author": "Behnam Azimi",
  "license": "ISC",
  "peerDependencies": {
    "react": "^16.9.0",
    "react-dom": "^16.9.0"
  },
  "devDependencies": {
    "@babel/core": "^7.6.0",
    "@babel/preset-env": "^7.6.0",
    "@babel/preset-react": "^7.0.0",
    "rollup": "^1.21.4",
    "rollup-plugin-babel": "^4.3.3",
    "rollup-plugin-commonjs": "^10.1.0",
    "rollup-plugin-uglify": "^6.0.3"
  }
}

在这些更改之后,npm link在我的ReactJS (Hooks)项目中真正起作用了

请注意,这只是一个简单的 Rollup 配置来显示我的解决方案,您可以向配置中添加多种内容,例如热重载、样式加载器和许多其他插件。