I am building a React library using webpack, and the library builds correctly into an es6
module. We are then trying to host this module on a CDN so we can import it through a url
instead of node_modules
.
We then import it like this, and I get the correct component.
import('http://example.com/test.js').then(m => console.log(m.default));
The library has this test component which works when I display it within the application:
This is exported through the library:
export default ({ name }) => {
return <div>{name}</div>;
};
The app then implements it like this:
export default () => {
const [Test, setTest] = useState();
useEffect(() => {
import('http://example.com/test.js').then(m => setTest(m.default));
}, []);
return <Test name="Joe" />;
}
However, when I add useState
, like this:
import { useState } from 'react';
export default ({ name }) => {
const [displayName] = useState('Billy');
return <div>{displayName}</div>;
};
I then get these two errors:
test.tsx:12 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:
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
react.development.js:1623 Uncaught TypeError: Cannot read properties of null (reading 'useState')
at useState (react.development.js:1623:21)
at default (test.tsx:12:76)
my webpack looks like this:
export default {
// module rules and entry snipped out
output: {
path: path.resolve(__dirname, '../../dist'),
filename: 'test.js',
library: {
type: 'module',
},
},
experiments: {
outputModule: true,
}
}
When I add externals: ['react', 'react-dom']
to webpack, I then get this error:
Uncaught (in promise) TypeError: Failed to resolve module specifier "react". Relative references must start with either "/", "./", or "../".
Why isn’t my library able to use useState
when loaded via a URL?
2
Answers
So, to get this to work, I needed to create a child app within the current application, so from the component that comes from a url sorce I also exported the react and react-dom so the parent application could create it:
Next, in the application I created a component that would bootstrap the data and display the internal application:
Lastly, I load the component from the remote and and pass it to the
Widget
. The widget then creates an application as a child of the current application:Looks like you haven’t excluded React packages from your library