I'm in an extremely weird situation where the project structure looks like:
Project
MiniProject1
MiniProject2
node_modules
package.json
The mini projects themselves are react apps that get shown within a ruby container. So when a user goes to /route1 it loads the miniProject1 react page. when they go to /route2 it goes to the miniProject2 page.
I've been tasked to update the react version of MiniProject2 but not interfere with MiniProject1 or make any changes that could interfere with MiniProject1.
I went the route of installing react and react-dom as follows:
"react-latest": "npm:react#^16.13.1",
"react-dom-latest": "npm:react-dom#^16.13.1",
so I can then import the latest versions specifically in MiniProject2
The problem that I'm facing is the react-dom has the "React" a peer dependency and it's trying to pull the project react instead of my aliased "react-latest" which makes sense but now I'm stuck trying to figure out how I can force react-dom to require my react-latest alias instead of the default react peer dependency.
I'm also open to potential Webpack config solutions.
Any thoughts?
After some digging I was able to force react-dom to use react-latest by doing the following:
package.json
"react": "^16.3.2",
"react-dom": "16.3.3",
"react-dom-latest": "npm:react-dom#^16.13.1",
"react-latest": "npm:react#^16.13.1",
webpack.config.js
module: {
rules: [
{
test: /\/node_modules\/react-dom-latest\/.*.js/,
resolve: {
alias: {
react: path.resolve('./node_modules/react-latest')
}
}
}]},
Then on the top of the files I need to use the latest react version for, I import react like so:
import React from 'react-latest'
//or
import ReactDOM from 'react-dom-latest' //for your index
On the files I need to use the old react for, I import react like so:
import React from 'react'
//or
import ReactDOM from 'react-dom' //for your index
That's all that needed to be done!
Disclaimer: Don't do this unless you have to and have no choice like I did. It'll increase the size of your bundle since you are bringing in two different versions of react and reactDom
Related
I'm using create-react-library to build my component library, and I've attempted to use Styled Components, but I keep getting a React hooks error.
Here's my code: https://github.com/emmabostian/component-library
And here's the error:
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
I am not using React hooks anywhere, my React and React DOM versions match and I do not have multiple versions of React.
Check your package.json file you appear to have dependencies react / react-dom version 16 but peer dependencies for versions 15 . I think this is the cause of your problem , remove the peer dependencies. Also you don't need to write your components as class based if all you are doing is rendering use a functional component approach instead.
The dependencies in the included example project are very outdated.
Instead I set up a new separate example project, which perfectly renders your button:
npx create-react-app component-library-example
cd component-library-example
npm install --save emmas-super-cool-component-library
npm start
App.js:
import React from "react";
import { PrimaryButton } from "emmas-super-cool-component-library";
const App = () => (
<PrimaryButton
onClickHandler={() => {
alert("clicked");
}}
>
text
</PrimaryButton>
);
export default App;
Result:
I've recently used create-react-library, and had encountered the same issue. The error message exactly makes sense in this case. The issue will not happen when you actually publish the package and consume it at a consumer application. This means, the problem is with your example folder. If you look at package.json, that's inside example folder, you can see there are library references for react, react-scripts, react-dom etc. Referring those with file protocol like below will solve your problem.
"dependencies": {
"library-name": "file:..",
"react": "file:../node_modules/react",
"react-dom": "file:../node_modules/react-dom",
"react-scripts": "file:../node_modules/react-scripts"
"node-sass": "file:../node_modules/node-sass"
},
Clear your node_modules as well as package-lock.json before trying this.
Hello every one i just want to know the mechanism behind how importing react from 'react' works in my cra-app but for my component i have to import it by defining the path of the component file in a nutshell why is there a difference between thee two statements
import React, { Component } from 'react';
import Button from './Button';
Thanks in advance
This is because React is using Webpack internally to resolve modules. In the first import import React, { Component } from 'react'; webpack will look for the library in the node_modules folder as it has a resolver configured to do so.
In the second case you need to mention the path or alias the path ./Button with a shorter name like 'button' to tell Webpack where to search/resolve in that directory inside the webpack.config.js.
For an app created using create-react-app, the webpack.config.js will be located in node_modules/react-scripts/config/webpack.config.js.
There you would notice this resolver is defined which tells Webpack where to look for the core libs:
resolve: {
// This allows you to set a fallback for where Webpack should look for modules.
// We placed these paths second because we want `node_modules` to "win"
// if there are any conflicts. This matches Node resolution mechanism.
// https://github.com/facebook/create-react-app/issues/253
modules: ['node_modules'].concat(
// It is guaranteed to exist because we tweak it in `env.js`
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
),
...
}
To alias your own path you can define a new alias in that file located in the config/webpack.config.js after you eject the app with npm run eject (you cannot undo this):
resolve: {
alias: {
'components' : path.resolve(__dirname, '../src/Components')
}
}
};
In you component you can import like:
import Button from 'components/Button';
react is a package installed via npm into node_mudules and can be imported by the package name.
Button is your custom component, and thus has to be imported by its path. If you made Button into a package, then you could install it via npm as well.
I create a react library using https://www.npmjs.com/package/create-react-library
And successfully used it on other React project.
But when I tried to use react hooks functionalities inside library it gives me following 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 Library
I just tried to use useState as follows in my component.
import React, { useState } from 'react'
const General = (props) => {
const [count, setCount] = useState(0);
return (
<div>
General component
</div>
)
}
export default General
I am using
"react": "^16.8.6" and "react-dom": "^16.8.6"
My React APP
Created a application using https://github.com/facebook/create-react-app and used above library as follows.
import Reactfrom 'react'
import { General } from 'my.lib'
const accountSummary = props => {
return (
<div>
<General>
</div>
)
}
export default accountSummary
Both has same react versions and library has used same react-dom and react versions as peerDependencies
I was including my component library (for that matter any library) in my application as #Janith did using my-comp-lib:"file:../.." (I don't want to publish every time I want to test) and I encountered the same issue.
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:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app See react-invalid-hook-call for tips about how to debug and
fix this problem
I was able to fix this by making my app and library point to the same react (package) location.
Below are the steps I followed :
1. In Your Application:
a) cd node_modules/react && npm link
b) cd node_modules/react-dom && npm link
2. In Your Library
a) npm link react
b) npm link react-dom
3)Stop your dev-server and do `npm start` again.
It works!!
Please refer below links for more details ..
https://github.com/facebook/react/issues/14721
https://github.com/facebook/react/pull/14690
https://github.com/facebook/react/issues/13991
Note : This issue will not happen if you publish your package to artifactory and install because you will have react & react-dom as peer-dependencies and they won't get included in the distribution. So your package and application use the same react which is installed in the application.
I just ran into the same issue. I was able to fix it by pointing to the same react in my example app as in my library:
App Structure
Root
Example
package.json
src (library)
package.json
So, from the example > package.json I changed react to be:
"react": "link:../node_modules/react",
This is much like the npm link listed above but it won't go away every time you npm install.
I had the same issue, working with a rush monorepo, configuring ui-package and building the apps using nextjs.
The solutions was add the follow code on package.json
"resolutions": {
"react": "17.0.1", // verificate your react version
"react-dom": "17.0.1"
}
In the library's package.json:
"peerDependencies": {
"react": "17.0.1",
"react-dom": "17.0.1"
},
See more here: https://github.com/vercel/next.js/issues/9022#issuecomment-728688452
Add to your Components Library's package.json
"peerDependencies": {
"react": "<your version>"
}
so that your lib package will use the same react package as your main app.
https://nodejs.org/es/blog/npm/peer-dependencies/
It worked for me when I changed the link from the app to the library to be "link:../" instead of "file:../", in addition to linking react and react-dom.
React 17 + React Testing Library + Umi(a frontend framework, built-in react-router)
In my case, when I run the unit test, I got an error message "invalid hook call".
After a period of trying, I found two ways to solve.
Downgrade to React 16.x, then all will be fine.
Keep using React 17.x, and
Still have to write import React from 'react'
Install react-router-dom separately
I think it may be a problem with react-router, but due to my limited understanding, I don't have a better solution yet.
Also check your npm version. My version was 7.0.8 which was outdated, after changing it to 6.14.8 everything was working fine!
WHEN TESTING WITH REAL APP IN REACT NATIVE
I have same issue and i delete my node_module file in my custom library and i fixed it..
issue when installing direct module
yarn add c:/user......./react-native-some-lib
In my case I'm building my own common library. Although I was exporting createContext, useContext and useState from "react", I simply forgot to also import the default export, React.
Changing my import statement from this:
import { createContext, useContext, useState } from "react";
to this:
import React, { createContext, useContext, useState } from "react";
fixed it for me. You might have to do this in every React component/context etc that you are exporting from your react library.
Edit:
In another one of my apps that relies on this common library, this issue was also fixed using npm link as described in the React documentation (Invalid Hook Call Warning):
This problem can also come up when you use npm link or an equivalent. In that case, your bundler might “see” two Reacts — one in application folder and one in your library folder. Assuming myapp and mylib are sibling folders, one possible fix is to run npm link ../myapp/node_modules/react from mylib. This should make the library use the application’s React copy.
So in my case, I navigated to my common library and ran npm link ../path-to-my-app/node_modules/react.
Edit (23/02/2022)
Hopefully the final edit - another solution is to simply globally install the problem dependency if all apps expect to use the same version, e.g. npm install react -g
I have created a React library with create-react-library this library is your General component. I have published it to npm here https://www.npmjs.com/package/stackoverflow-test and a React app for use it here https://codesandbox.io/s/mm7yl83o28.
Just click on General component text and count will be incremented.
I cannot reproduce your issue, just use this test to check your implementation.
I have an application where I have to build code using babel and react. The application will be built using gulp and webpack for automated build creation and deployment. When using gulp and webpack to convert babel+react code to browser interpretable code, we need to install react using npm and has to be imported in all files, following is the sample code:
import React from 'react';
import ReactDOM from 'react-dom';
import HelloWorld from './helloWorld.jsx';
import HelloMe from './hello-me.jsx';
ReactDOM.render(
<HelloWorld />,
document.getElementById('app-test')
);
ReactDOM.render(
<HelloMe />,
document.getElementById('app-container')
);
Now, the problem is this code when bundled with webpack, bundles react and react-dom library code to the bundled file. So, I would not be able to cache these library files to be loaded in different views. Due to this, the same library code will load again and again in different bundled files. Is there a way to load these files separately and not in the bundled file?
Edit your Wabpack configuration file and specify React & ReactDOM as externals.
externals: {
"react": "React",
"react-dom": "ReactDOM",
},
Then, include React & ReactDOM from CDN or your prefered source.
Whenever you call import React from 'react' or require('react') (or react-dom), Webpack gives you external copy of library
I face the same issue as described here
https://github.com/babel/babel/issues/2504
So, any file which has only stateless components needs to have react imported like import React from 'react';, which is bit annoying (eslint gives error as unused variable; which I understand can be suppressed, still..). Is there a way to avoid having this import in a webpack based setup.
thanks.
I had the same issue. Then, I found this:
babel-plugin-react-require
This will automatically add the required require or import calls to get 'react' imported to your stateless component modules.
P.S. If you use webpack and babel6, ensure that you are not using the jsx-loader for your JSX files. I was getting errors with this and then I realized the jsx-loader is not required anymore. Just use:
babel-preset-react
You can use Webpack's ProvidePlugin (https://github.com/webpack/docs/wiki/shimming-modules#plugin-provideplugin):
new webpack.ProvidePlugin({
React: "react"
})
Now you'll have React available in every module without having to explicitly write import React from 'react'