React项目useHistory.push报错及process未定义问题求助
错误1:Uncaught TypeError: 无法读取未定义属性(读取'push')
错误详情
Uncaught TypeError: 无法读取未定义属性(读取'push')
在Main.components_speechRecognition_SpeechRecognition__WEBPACK_IMPORTED_MODULE_12.recognition.onresult
(Main.js:22:1)
Main.components_speechRecognition_SpeechRecognition__WEBPACK_IMPORTED_MODULE_12.recognition.onresult
@ Main.js:22
原因
useHistory钩子必须在路由上下文(HashRouter/BrowserRouter)的子组件中调用。当前代码里Main组件先调用useHistory,再在return里渲染HashRouter,导致history无法获取路由上下文,变成undefined,调用push就会报错。另外,全局recognition的回调绑定没有清理,还可能引发内存泄漏。
解决办法
- 把语音识别逻辑封装成独立组件,放到
HashRouter内部,确保能获取到路由上下文; - 用
useEffect管理recognition的事件监听,组件卸载时移除监听,避免内存泄漏; - 调用
history.push时用可选链?.,防止history为undefined时出错。
错误2:Uncaught ReferenceError: process未定义
错误详情
VM338:2 Uncaught ReferenceError: process未定义
在4043 (:2:13168)
在r (:2:306599)
在8048 (:2:9496)
在r (:2:306599)
在8641 (:2:1379)
在r (:2:306599)
在:2:315627
在:2:324225
在:2:324229
在e.onload (index.js:1:1)
原因
Webpack 5+或Vite这类构建工具不再默认注入process全局变量,你的项目里有依赖(比如portfolio.js或其他库)引用了process.env,导致浏览器环境找不到这个变量。
解决办法
如果你用的是Create React App:
- 检查第三方库是否依赖
process,尝试更新到最新版本; - 自己代码里用了
process.env的话,换成import.meta.env(CRA 5+支持),或者确保环境变量配置正确。
如果你用的是Webpack 5:
在webpack.config.js中添加DefinePlugin配置,手动注入process变量:
const webpack = require('webpack'); module.exports = { // 其他配置... plugins: [ new webpack.DefinePlugin({ 'process.env': JSON.stringify(process.env) }) ] };
如果你用的是Vite:
在vite.config.js中配置define:
export default { define: { 'process.env': {} } };
如果需要具体环境变量,直接用Vite的import.meta.env代替process.env。
修改后的完整Main组件代码
import React, { useEffect } from "react"; import { Route, Switch, HashRouter, useHistory } from "react-router-dom"; import Home from "../pages/home/HomeComponent"; import Splash from "../pages/splash/Splash"; import Education from "../pages/education/EducationComponent"; import Experience from "../pages/experience/Experience"; import Contact from "../pages/contact/ContactComponent"; import Projects from "../pages/projects/Projects"; import HobbiesPage from "../pages/hobbies/Hobbies"; import { settings } from "../portfolio.js"; import GamingPage from "../pages/gaming/gaming"; import AnimePage from "../pages/anime/Anime"; import { recognition } from "../components/speechRecognition/SpeechRecognition"; // 封装语音导航逻辑,确保在路由上下文内 const SpeechNavigation = () => { const history = useHistory(); useEffect(() => { const handleResult = (event) => { const command = event.results[0][0].transcript; if (command.includes("navigate to") || command.includes("go to")) { if (command.includes("home") || command.includes("index")) { history?.push("/home"); } else if (command.includes("education")) { history?.push("/education"); } else if (command.includes("experience")) { history?.push("/experience"); } else if (command.includes("contact")) { history?.push("/contact"); } } }; const handleEnd = () => { recognition.start(); }; // 绑定事件 recognition.addEventListener('result', handleResult); recognition.addEventListener('end', handleEnd); recognition.start(); // 卸载时清理 return () => { recognition.removeEventListener('result', handleResult); recognition.removeEventListener('end', handleEnd); recognition.stop(); }; }, [history]); return null; }; export default function Main(propss) { return ( <div> <HashRouter basename="/"> <SpeechNavigation /> <Switch> {settings.isSplash ? ( <Route path="/" exact render={(props) => ( <Splash {...props} theme={propss.theme} setTheme={propss.setTheme} /> )} /> ) : ( <Route path="/" exact render={(props) => ( <Home {...props} theme={propss.theme} setTheme={propss.setTheme} /> )} /> )} <Route path="/home" render={(props) => ( <Home {...props} theme={propss.theme} setTheme={propss.setTheme} /> )} /> <Route path="/experience" exact render={(props) => ( <Experience {...props} theme={propss.theme} setTheme={propss.setTheme} /> )} /> <Route path="/education" render={(props) => ( <Education {...props} theme={propss.theme} setTheme={propss.setTheme} /> )} /> <Route path="/contact" render={(props) => ( <Contact {...props} theme={propss.theme} setTheme={propss.setTheme} /> )} /> {settings.isSplash && ( <Route path="/splash" render={(props) => ( <Splash {...props} theme={propss.theme} setTheme={propss.setTheme} /> )} /> )} <Route path="/projects" render={(props) => ( <Projects {...props} theme={propss.theme} setTheme={propss.setTheme} /> )} /> <Route path="/hobbies" render={(props) => ( <HobbiesPage {...props} theme={propss.theme} setTheme={propss.setTheme} /> )} /> <Route path="/gaming" render={(props) => ( <GamingPage {...props} theme={propss.theme} setTheme={propss.setTheme} /> )} /> <Route path="/anime" render={(props) => ( <AnimePage {...props} theme={propss.theme} setTheme={propss.setTheme} /> )} /> </Switch> </HashRouter> </div> ); }
内容的提问来源于stack exchange,提问作者Moe_blg

