My React App was working perfectly, but after upgrading to React 18, MUI v5 and Redux v5 it is not rendering anything.
In the terminal I’m getting: "webpack compiled successfully"
But in the Chrome console, I’m getting:
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.
printWarning @ react.development.js:209
error @ react.development.js:183
resolveDispatcher @ react.development.js:1592
useContext @ react.development.js:1602
useReduxContext2 @ useReduxContext.ts:14
useSelector2 @ useSelector.ts:175
NoLogin @ auth.js:23
./src/routes/index.js @ index.js:9
options.factory @ react refresh:6
__webpack_require__ @ bootstrap:22
fn @ hot module replacement:61
./src/routes/Routes.js @ index.js:13
options.factory @ react refresh:6
__webpack_require__ @ bootstrap:22
fn @ hot module replacement:61
./src/App.js @ bundle.js:25
options.factory @ react refresh:6
__webpack_require__ @ bootstrap:22
fn @ hot module replacement:61
./src/index.js @ Sidebar.js:420
options.factory @ react refresh:6
__webpack_require__ @ bootstrap:22
(anonymous) @ startup:7
(anonymous) @ startup:7
Show 6 more frames
Show less
react.development.js:1618
Uncaught TypeError: Cannot read properties of null (reading 'useContext')
at Object.useContext (react.development.js:1618:1)
at useReduxContext2 (useReduxContext.ts:14:1)
at useSelector2 (useSelector.ts:175:1)
at NoLogin (auth.js:23:1)
at ./src/routes/index.js (index.js:9:1)
at options.factory (react refresh:6:1)
at __webpack_require__ (bootstrap:22:1)
at fn (hot module replacement:61:1)
at ./src/routes/Routes.js (index.js:13:1)
at options.factory (react refresh:6:1)`
This is my package.json
:
{
"name": ********************,
"version": "0.0.1",
"private": true,
"homepage": ********************
"scripts": {
"start": ********************
"start:local": ********************
"start:sg": ********************
"build:dev": ********************
"build": *********************
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 10",
"not op_mini all"
],
"peerDependencies": {
"react": "^17.0.0 || ^18.0.0",
"react-dom": "^17.0.0 || ^18.0.0"
},
"dependencies": {
"@date-io/date-fns": "^3.0.0",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@iconify/react": "^4.1.1",
"@mui/lab": "^5.0.0-alpha.170",
"@mui/material": "^5.15.15",
"@mui/styled-engine": "^5.15.14",
"@mui/x-date-pickers": "^7.2.0",
"@reduxjs/toolkit": "^2.2.3",
"axios": "^1.6.8",
"chart.js": "^4.4.2",
"clsx": "^2.1.0",
"date-fns": "^3.6.0",
"env-cmd": "^10.1.0",
"i18n-iso-countries": "^7.10.0",
"immer": "^10.0.3",
"material-ui-confirm": "^3.0.12",
"moment": "^2.30.1",
"mui-datatables": "^4.3.0",
"notistack": "^3.0.1",
"numeral": "^2.0.6",
"polished": "^4.1.3",
"prop-types": "^15.7.2",
"react": "^17.0.0 || ^18.0.0",
"react-app-polyfill": "^3.0.0",
"react-dom": "^17.0.0 || ^18.0.0",
"react-feather": "^2.0.10",
"react-perfect-scrollbar": "^1.5.8",
"react-redux": "^9.1.1",
"react-router-dom": "^6.22.3",
"react-scripts": "^5.0.1",
"react-select": "^5.2.0",
"redux": "^5.0.1",
"redux-auth-wrapper": "^3.0.0",
"redux-saga": "^1.1.3",
"reselect": "^5.1.0",
"styled-components": "^6.1.8",
"url": "^0.11.3"
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11"
}
}
This is my App.js
:
import React from "react";
import { connect } from "react-redux";
import { BrowserRouter as Router } from "react-router-dom";
import { ThemeProvider, StyledEngineProvider } from "@mui/material/styles";
import AdapterDateFns from '@mui/lab/AdapterDateFns';
import LocalizationProvider from '@mui/lab/LocalizationProvider';
import { SnackbarProvider } from "notistack";
import maTheme from "./theme";
import Routes from "./routes/Routes";
import { ConfirmProvider } from 'material-ui-confirm';
const App = ({ theme }) => {
return (
<StyledEngineProvider injectFirst>
<ThemeProvider theme={maTheme[theme.currentTheme]}>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<ConfirmProvider>
<SnackbarProvider maxSnack={1}>
<Routes />
</SnackbarProvider>
</ConfirmProvider>
</LocalizationProvider>
</ThemeProvider>
</StyledEngineProvider>
);
};
const ConnectedApp = connect(store => ({ theme: store.themeReducer }))(App);
function AppWithRouter() {
return (
<Router>
<ConnectedApp/>
</Router>
);
}
export default AppWithRouter;`
This is my index.js
:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Provider } from 'react-redux';
import store from './redux/store/index';
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<Provider store={store}>
<App tab="home"/>
</Provider>
</React.StrictMode>
);
This is my Routes/index.js
:
import React from "react";
import async from "../components/Async";
import { Truck } from "react-feather";
import {NeedsLogin, NoLogin} from "./auth";
// Auth components
const SignIn = NoLogin(() => import("../pages/auth/SignIn"));
const SignUp = async(() => import("../pages/auth/SignUp"));
const ForgotPassword = async(() => import("../pages/auth/ForgotPassword"));
const ResetPassword = async(() => import("../pages/auth/ResetPassword"));
const Page404 = async(() => import("../pages/auth/Page404"));
const Page500 = async(() => import("../pages/auth/Page500"));
// Pages components
const OnBoard = NeedsLogin(() => import("../pages/pages/OnBoard"));
const Institutions = NeedsLogin(() => import("../pages/pages/Institutions/Institutions"));
const LoginInstitutions = NeedsLogin(() => import("../pages/pages/Institutions/LoginInstitution"));
const Instances = NeedsLogin(() => import("../pages/pages/Instances/Instances"));
const EditInstance = NeedsLogin(() => import("../pages/pages/Instances/editInstance"));
//Account Routes
const MyAccount = NeedsLogin(() => import("../pages/pages/Account/MyAccount"));
const homeRoutes = {
id: "Home",
path: "/",
component: OnBoard,
children: null,
hidden: true
};
const accountRoutes = {
id: "My Account",
path: "/my_account",
component: MyAccount,
children: null,
hidden: true
};
const institutionsRoutes = {
id: "Institutions",
path: "/institutions",
component: Institutions,
children: null,
hidden: true
};
const loginInstitutionsRoutes = {
id: "Distribution Institutions",
path: "/login_institutions",
component: LoginInstitutions,
icon: <Truck />,
children: null,
};
const instancesRoutes = {
id: "Instances",
path: "/instances",
component: Instances,
children: null,
hidden: true
};
const editInstanceRoutes = {
id: "Edit Instance",
path: "/editInstance",
component: EditInstance,
children: null,
hidden: true
};
const authRoutes = {
id: "Auth",
path: "/auth",
hidden: true,
children: [
{
path: "/auth/sign-in",
name: "Sign In",
component: SignIn
},
{
path: "/auth/sign-up",
name: "Sign Up",
component: SignUp
},
{
path: "/auth/forgot-password",
name: "Forgot Password",
component: ForgotPassword
},
{
path: "/reset_your_password/:id",
name: "Reset Password",
component: ResetPassword
},
{
path: "/auth/404",
name: "404 Page",
component: Page404
},
{
path: "/auth/500",
name: "500 Page",
component: Page500
}
]
};
export const dashboard = [
homeRoutes,
accountRoutes,
institutionsRoutes,
instancesRoutes,
editInstanceRoutes,
loginInstitutionsRoutes
];
export const auth = [authRoutes];
export default [
homeRoutes,
accountRoutes,
authRoutes,
institutionsRoutes,
instancesRoutes,
editInstanceRoutes,
loginInstitutionsRoutes
];
This my auth.js
:
import { useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import Loader from '../components/Loader';
const NeedsLogin = ({ children }) => {
const signedIn = useSelector(state => state.auth.signedIn);
const loading = useSelector(state => state.auth.loading);
const history = useNavigate();
if (loading) {
return <Loader />;
}
if (!signedIn) {
history('/auth/sign-in');
return null;
}
return children;
};
const NoLogin = ({ children }) => {
const signedIn = useSelector(state => state.auth.signedIn);
const loading = useSelector(state => state.auth.loading);
const history = useNavigate();
if (loading) {
return <Loader />;
}
if (signedIn) {
history('/');
return null;
}
return children;
};
export { NeedsLogin, NoLogin };
I tried deleting the React.StrictMode
and got the same result.
I checked react and react-dom versions in my project with:
npm ls react-dom
├─┬ @mui/[email protected]
│ ├─┬ @mui/[email protected]
│ │ ├─┬ @floating-ui/[email protected]
│ │ │ └── [email protected] deduped
│ │ └── [email protected] deduped
│ └── [email protected] deduped
├─┬ @mui/[email protected]
│ ├── [email protected] deduped
│ └─┬ [email protected]
│ └── [email protected] deduped
├─┬ @mui/[email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected] deduped
│ ├── [email protected] deduped
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected] deduped
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected] deduped
│ └─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├── [email protected]
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
└─┬ [email protected]
└── [email protected] deduped
npm ls react
├─┬ @emotion/[email protected]
│ ├─┬ @emotion/[email protected]
│ │ └── [email protected] deduped
│ └── [email protected] deduped
├─┬ @emotion/[email protected]
│ └── [email protected] deduped
├─┬ @iconify/[email protected]
│ └── [email protected] deduped
├─┬ @mui/[email protected]
│ ├─┬ @mui/[email protected]
│ │ ├─┬ @floating-ui/[email protected]
│ │ │ └── [email protected] deduped
│ │ └── [email protected] deduped
│ ├─┬ @mui/[email protected]
│ │ ├─┬ @mui/[email protected]
│ │ │ └── [email protected] deduped
│ │ └── [email protected] deduped
│ ├─┬ @mui/[email protected]
│ │ └── [email protected] deduped
│ └── [email protected] deduped
├─┬ @mui/[email protected]
│ ├─┬ [email protected]
│ │ └── [email protected] deduped
│ └── [email protected] deduped
├─┬ @mui/[email protected]
│ └── [email protected] deduped
├─┬ @mui/[email protected]
│ └── [email protected] deduped
├─┬ @reduxjs/[email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ ├─┬ @mui/[email protected]
│ │ └── [email protected] deduped
│ ├─┬ [email protected]
│ │ └── [email protected] deduped
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected] deduped
│ │ ├─┬ [email protected]
│ │ │ └── [email protected] deduped
│ │ ├─┬ [email protected]
│ │ │ └── [email protected] deduped
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected] deduped
│ ├── [email protected] deduped
│ └─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ ├── [email protected] deduped
│ └─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected] deduped
│ └── [email protected] deduped
├─┬ [email protected]
│ └── [email protected] deduped
├─┬ [email protected]
│ ├── [email protected] deduped
│ └─┬ [email protected]
│ └── [email protected] deduped
├── [email protected]
└─┬ [email protected]
└── [email protected] deduped
I tried uninstalling mui-datatables but it is still the same.
2
Answers
Try using a single version of react and react-dom in your package.json file (like in the snippet mentioned above), un-install your node modules folder and do a fresh npm install.
The issue may be with the dependency:
react-sortable-tree-patch-react-17
which is pulling in v17 ofreact
andreact-dom
.Looking at the dependent package
mui-datatables
this may still be an issue.If you are using a relatively new version of
npm
, you could addoverrides
to force the same version ofreact
andreact-dom
to18.2.0
. Or ifyarn
is an option, you can add similar configresolutions
.In your
package.json
add the following, then cleanly install your dependencies by deleting./node_modules
andpackage-lock.json
before runningnpm i
.However this could have side effects in the library still expecting react v17.