Reputation: 1
Updates:
Here is the complete error
my-lib.iife.js?ver=1.0:9 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
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
my-lib.iife.js?ver=1.0:21 Uncaught TypeError: Cannot read properties of null (reading 'useState')
Here is my package.json
{
"name": "my-lib",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "NODE_ENV=development vite build",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@mui/icons-material": "^5.15.14",
"@mui/material": "^5.15.14",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@vitejs/plugin-react-swc": "^3.5.0",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"vite": "^5.2.0"
}
}
I think I'm using right version of react-dom for react. The hook is used in function component as its first instruction. I'm not including more then a copy of react, I'm not including react at all except in the bundle.
Tried also webpack (libraryTarget: "var"), but get the exact same error.
I am trying to create a library of React components. The goal is to call them like this:
<div id="testreact"></div>
<div id="testreact2"></div>
<script>
MyLib.ReactDOM.createRoot(document.getElementById('testreact')).render(
MyLib.ButtonShowdown(),
)
MyLib.ReactDOM.createRoot(document.getElementById('testreact2')).render(
MyLib.DrawerShowdown(),
)
</script>
ButtonShowdown works correctly.
DrawerShowdown utilizes React.useState, but I receive the error "Cannot read properties of null (reading 'useState')" in the console.
The build is done in Vite using this configuration:`
import { defineConfig } from 'vite'
import { resolve } from 'path';
import react from '@vitejs/plugin-react-swc'
export default defineConfig({
define: {
'process.env': process.env
},
plugins: [react()],
build: {
lib: {
entry: resolve(__dirname, 'lib/main.js'),
name: 'MyLib',
fileName: 'my-lib',
formats: ['iife']
}
},
})
lib/main.js
import ReactDOM from 'react-dom/client'
import ButtonShowdown from "../src/ButtonShowdown";
import DrawerShowdown from "../src/DrawerShowdown"
export {
ReactDOM,
ButtonShowdown,
DrawerShowdown,
};
It seems that many have resolved it by excluding React and ReactDOM from the library, but doing so causes ButtonShowdown to stop working as well.
Although I believe it might be redundant, I'll provide the code for the components:
import React from 'react'
import { Button } from "@mui/material";
import Base from "./Base";
function ButtonShowdown(){
return (
<Base>
<div>Showdown:</div>
<Button variant="text">Text</Button>
<Button variant="contained">Contained</Button>
<Button variant="outlined">Outlined</Button>
</Base>
)
}
export default ButtonShowdown;
import React from 'react';
import Box from '@mui/material/Box';
import Drawer from '@mui/material/Drawer';
import Button from '@mui/material/Button';
import List from '@mui/material/List';
import Divider from '@mui/material/Divider';
import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import InboxIcon from '@mui/icons-material/MoveToInbox';
import MailIcon from '@mui/icons-material/Mail';
import Base from './Base';
function DrawerShowdown() {
const [open, setOpen] = React.useState(false);
const toggleDrawer = (newOpen) => () => {
setOpen(newOpen);
};
const DrawerList = (
<Box sx={{ width: 250 }} role="presentation" onClick={toggleDrawer(false)}>
<List>
{['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
<ListItem key={text} disablePadding>
<ListItemButton>
<ListItemIcon>
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
</ListItemIcon>
<ListItemText primary={text} />
</ListItemButton>
</ListItem>
))}
</List>
<Divider />
<List>
{['All mail', 'Trash', 'Spam'].map((text, index) => (
<ListItem key={text} disablePadding>
<ListItemButton>
<ListItemIcon>
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
</ListItemIcon>
<ListItemText primary={text} />
</ListItemButton>
</ListItem>
))}
</List>
</Box>
);
return (
<Base>
<Button onClick={toggleDrawer(true)}>Open drawer</Button>
<Drawer open={open} onClose={toggleDrawer(false)}>
{DrawerList}
</Drawer>
</Base>
);
}
export default DrawerShowdown;
import React from 'react'
import { ScopedCssBaseline, ThemeProvider, createTheme } from "@mui/material";
import { red } from '@mui/material/colors';
function Base({children}){
const baseTheme = createTheme(window.WpeaUI?.customTheme ?? {
/*palette: {
primary: red
}*/
});
return (
<React.StrictMode>
<ScopedCssBaseline>
<ThemeProvider theme={baseTheme}>
{children}
</ThemeProvider>
</ScopedCssBaseline>
</React.StrictMode>
)
}
export default Base;
As long as I execute npm run dev, everything works correctly. However, as soon as I try the bundle, for DrawerShowdown I receive the error: "Cannot read properties of null (reading 'useState')".
Upvotes: 0
Views: 368
Reputation: 29
This may not be the answer, but try to externalize any dependencies you do not want to bundle into your library, such as react
and react-dom
.
build: {
...,
rollupOptions: {
external: ['react', 'react-dom']
},
}
Also, in your package.json
, make sure React and ReactDOM are listed as peer dependencies.
Upvotes: 0