Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicate ReactJS import issue when using npm link to test component before publishing as npm package

I have a simple component like this.

import React, {useState} from 'react';

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

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

export default MyComponentWithState;

and I want to publish it on NPM as a separate package. so, to do that I prepared package.json and webpack.config.js like below.

package.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"
    },
};

and here is my .babelrc:

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

These configs work like charm when I publish my component to NPM and install it in my another ReactJs project with `npm install , but my point is the local test!

I want to test this component/lib before publish. To do this I use npm link feature to link my component with my main ReactJS project.

As you saw above, my component is functional and I used hooks too. So when I inject the locally linked lib to my main ReactJs project face this 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

My issue is related to the 3td reason. My project uses ReactJs and import it once and also my component will import React! I mean twice React import in one project!.

I also have externals config about react and react-dom in my Webpack config.

What should I do to solve that? Where is my mistake?

Update: I also tried what @sung-m-kim and @eddie-cooro say but it not worked! Mean, I change the package.json and removed react and react-dom from dependencies and add them to devDpendencies.

like image 673
Behnam Azimi Avatar asked Sep 10 '19 13:09

Behnam Azimi


People also ask

How do you solve You might have more than one copy of React in the same app?

4 answers. In the module you are developing, add the conflicting packages to peerDependencies (and remove them from dependencies or devDependencies ): // package. json "peerDependencies": { "react": "16.13.

How do I unlink a node module?

You can “undo” the effects of npm link by simply removing the symbolic links. But there is a built in command for it, aptly called: npm unlink . Just run npm unlink --no-save <module_name> on your project's directory to remove the local symlink, and run npm unlink on the module's directory to remove the global symlink.


1 Answers

I finally solved this problem by these steps.

run npm link inside

<your-library-package>/node_modules/react

also

run npm link inside

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

then run npm link react and npm link react-dom inside your application root directory

and dont forget to keep react and react-dom as externals in the library

// webpack.config.js

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

module.exports = {
    .
    .
    .

   externals
   }
like image 139
armin yahya Avatar answered Sep 23 '22 11:09

armin yahya