React Typescript报错:在<Router>外使用<withRouter(App)>该如何解决?
问题根因
报错的核心原因是React Router提供的withRouter高阶组件、useHistory钩子都只能在被<Router>组件包裹的后代组件中调用,你当前的代码结构存在顺序错误:你在<App>组件内部才渲染<Router>,但是<App>本身先被withRouter封装,还在组件顶层调用了useHistory,相当于路由上下文还没初始化就提前调用了路由相关API,自然触发报错。
修复步骤
- 把
<Router>组件从App.tsx中移到项目入口文件(通常是index.tsx),用来包裹整个App组件,保证App内部所有组件都能拿到路由上下文 - 删除App组件的
withRouter封装,函数组件直接使用useHistory即可,无需额外包裹高阶组件 - 补全useEffect的依赖项,避免逻辑重复触发
入口文件index.tsx参考代码
import React from 'react'; import ReactDOM from 'react-dom/client'; import { BrowserRouter as Router } from 'react-router-dom'; import { Provider } from 'react-redux'; import App from './App'; import store from './store'; // 替换为你实际的store路径 const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement); root.render( <Provider store={store}> {/* Router移到此处包裹App */} <Router> <App /> </Router> </Provider> );
修改后App.tsx代码
import React, { FC, useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; import { Route, Switch, useHistory, } from "react-router-dom"; import "./App.css"; import Header from "./components/sections/Header"; import SignUp from "./components/pages/SignUp"; import SignIn from "./components/pages/SignIn"; import ForgotPassword from "./components/pages/ForgotPassword"; import Homepage from "./components/pages/Homepage"; import Dashboard from "./components/pages/Dashboard"; import PrivateRoute from "./components/auth/PrivateRoute"; import PublicRoute from "./components/auth/PublicRoute"; import Loader from "./components/UI/Loader"; import firebase from "./firebase/config"; import { getUserById, setLoading, setNeedVerification, } from "./store/actions/authActions"; import { RootState } from "./store"; const App: FC = () => { const dispatch = useDispatch(); const { loading } = useSelector((state: RootState) => state.auth); const history = useHistory(); useEffect(() => { dispatch(setLoading(true)); const unsubscribe = firebase.auth().onAuthStateChanged(async (user) => { if (user) { await dispatch(getUserById(user.uid)); if (user.emailVerified) { history.push("/homepage"); } else { history.push("/signin"); dispatch(setNeedVerification()); } } dispatch(setLoading(false)); }); return () => { unsubscribe(); }; // 补全依赖项避免重复执行 }, [dispatch, history]); if (loading) { return <Loader />; } function Routes() { return ( <Switch> <PublicRoute path="/signup" component={SignUp} exact /> <PublicRoute path="/signin" component={SignIn} exact /> <PublicRoute path="/forgot-password" component={ForgotPassword} exact /> <PrivateRoute path="/dashboard" component={Dashboard} exact /> <PublicRoute path="/homepage" component={Homepage} exact /> </Switch> ); } // 去掉外层Router标签,已经在入口文件包裹 return ( <> <Header /> <Routes /> </> ); }; // 去掉withRouter封装 export default App;
内容的提问来源于stack exchange,提问作者Manuel Lucas
相关产品推荐
相关产品推荐

