You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Material-UI TextField组件触发Invalid Hook Call错误排查求助

解决React中Material-UI TextField触发Invalid Hook Call错误

问题现象

  • 使用Material-UI的TextField组件时触发Invalid Hook Call错误,原生input可正常渲染
  • 错误栈指向Material-UI内部的useTheme、useStyles等钩子调用

错误日志

react-refresh-runtime.development.js:315 Uncaught 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
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
   at resolveDispatcher (react.development.js:1476:1)
   at Object.useContext (react.development.js:1484:1)
   at useTheme (useTheme.js:4:1)
   at useStyles (makeStyles.js:222:1)
   at WithStyles (withStyles.js:55:1)
   at renderWithHooks (react-dom.development.js:16305:1)
   at updateForwardRef (react-dom.development.js:19226:1)
   at beginWork (react-dom.development.js:21636:1)
   at beginWork$1 (react-dom.development.js:27426:1)
   at performUnitOfWork (react-dom.development.js:26557:1)

相关代码

Login组件

import React, { useState } from "react";
import { loginUser } from "../redux/user";
import { useSelector, useDispatch } from "react-redux";
import { Button, TextField } from "@material-ui/core";

const Login = () => {
  const dispatch = useDispatch();
  const { user, status } = useSelector((state) => state.user);

  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const login = async () => {
    let obj = { email, password };
    await dispatch(loginUser({ obj: obj }));
    await console.log(user);
    await console.log(status);
  };

  return (
    <div>
      <TextField />
    </div>
  );
};

export default Login; 

package.json依赖

"dependencies": {
    "@emotion/react": "^11.10.4",
    "@emotion/styled": "^11.10.4",
    "@mui/icons-material": "^5.10.3",
    "@mui/material": "^5.10.3",
    "@reduxjs/toolkit": "^1.8.5",
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.3.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^0.27.2",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-redux": "^8.0.2",
    "react-router-dom": "^6.3.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },

Index.js

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import store from "./redux/store";
import { Provider } from "react-redux";

import Login from "./pages/Login";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<App />} />
          <Route path="/login" element={<Login />} />
          <Route
            path="*"
            element={
              <main>
                <p>Oops, you went to wrong route. Please try another.</p>
              </main>
            }
          />
        </Routes>
      </BrowserRouter>
    </Provider>
  </React.StrictMode>
);

reportWebVitals();

userSlice.js

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";

export const loginUser = createAsyncThunk("user/Login", async ({ obj }) => {
  return axios
    .post("http://127.0.0.1:8000/api/login", {
      email: obj.email,
      password: obj.password,
    })
    .then(function (response) {
      return response.data;
    })
    .catch(function (error) {
      console.log(error);
    });
});

export const userSlice = createSlice({
  name: "user",
  initialState: {
    user: null,
    status: null,
  },
  extraReducers: {
    [loginUser.pending]: (state, action) => {
      state.status = "loading";
    },
    [loginUser.fulfilled]: (state, action) => {
      state.user = action.payload;
      state.status = "success";
    },
    [loginUser.rejected]: (state, action) => {
      state.status = "rejected";
    },
  },
});

export default userSlice.reducer;

npm ls react结果

+-- @emotion/react@11.10.4
| +-- @emotion/use-insertion-effect-with-fallbacks@1.0.0
| | `-- react@18.2.0 deduped
| `-- react@18.2.0 deduped
+-- @emotion/styled@11.10.4
| `-- react@18.2.0 deduped
+-- @mui/icons-material@5.10.3
| `-- react@18.2.0 deduped
+-- @mui/material@5.10.3
| +-- @mui/base@5.0.0-alpha.95
| | `-- react@18.2.0 deduped
| +-- @mui/system@5.10.3
| | +-- @mui/private-theming@5.10.3
| | | `-- react@18.2.0 deduped
| | +-- @mui/styled-engine@5.10.3
| | | `-- react@18.2.0 deduped
| | `-- react@18.2.0 deduped
| +-- @mui/utils@5.10.3
| | `-- react@18.2.0 deduped
| +-- react-transition-group@4.4.5
| | `-- react@18.2.0 deduped
| `-- react@18.2.0 deduped
+-- @reduxjs/toolkit@1.8.5
| `-- react@18.2.0 deduped
+-- @testing-library/react@13.3.0
| `-- react@18.2.0 deduped
+-- react-dom@18.2.0
| `-- react@18.2.0 deduped
+-- react-redux@8.0.2
| +-- react@18.2.0 deduped
| `-- use-sync-external-store@1.2.0
|   `-- react@18.2.0 deduped
+-- react-router-dom@6.3.0
| +-- react-router@6.3.0
| | `-- react@18.2.0 deduped
| `-- react@18.2.0 deduped
+-- react-scripts@5.0.1
| `-- react@18.2.0 deduped
`-- react@18.2.0

解决方案

从依赖和npm ls react结果来看,你同时安装了旧版Material-UI(@material-ui/core)和新版MUI(@mui/material),两者冲突导致钩子调用错误。

具体步骤:

  1. 卸载旧版Material-UI:
    npm uninstall @material-ui/core
    
  2. 替换组件导入路径:
    将Login组件中的导入代码修改为:
    import { Button, TextField } from "@mui/material";
    
  3. 清除缓存并重启项目:
    rm -rf node_modules package-lock.json
    npm install
    npm start
    

原因说明:

@material-ui/core是Material-UI v4版本,@mui/material是v5版本,两者不能共存。v4的内部API(如makeStyles、withStyles)未适配React 18的并发特性,且和v5的主题系统冲突,从而触发钩子调用错误。

内容的提问来源于stack exchange,提问作者Marco Ávila

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:36:52