React 17+TypeScript使用react-router-dom 6.0.2配置路由时遇[ProxyFacade]非Route组件错误求助
解决React Router 6 + React 17 + TypeScript中的[ProxyFacade]路由错误
我之前也踩过这个坑,这个错误的核心原因是**react-hot-loader的热加载包装逻辑打乱了React Router 6对路由组件结构的校验规则**。React Router 6对<Routes>的直接子元素有非常严格的要求——必须是<Route>或者<React.Fragment>,但hot(module)(App)会把你的根组件包裹成一个ProxyFacade代理组件,导致React Router无法识别原本合法的路由层级。
下面是两种可行的解决方案:
方案1:替换react-hot-loader为react-refresh(推荐)
react-hot-loader已经停止维护,React 17及后续版本官方推荐用react-refresh实现热加载,步骤如下:
- 卸载旧依赖:
npm uninstall react-hot-loader # 或使用yarn yarn remove react-hot-loader
- 安装新的热加载依赖:
npm install --save-dev @pmmmwh/react-refresh-webpack-plugin react-refresh # 或使用yarn yarn add --dev @pmmmwh/react-refresh-webpack-plugin react-refresh
- 配置Webpack(如果用Create React App则无需手动配置,它已内置支持):
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); module.exports = { // ...其他现有配置 plugins: [ // ...其他插件 new ReactRefreshWebpackPlugin(), ], module: { rules: [ { test: /\.[jt]sx?$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', options: { // ...其他Babel配置 plugins: [require.resolve('react-refresh/babel')], }, }, ], }, ], }, };
- 简化App.tsx,移除
react-hot-loader相关代码:
import * as React from "react"; import "./index.less"; import { BrowserRouter, Route, Routes } from "react-router-dom"; import SignIn from "../sign-in"; import SignUp from "../sign-up"; const App = () => { return ( <BrowserRouter> <Routes> <Route path="/" element={<SignIn />} /> <Route path="/signup" element={<SignUp />} /> </Routes> </BrowserRouter> ); }; export default App;
方案2:临时绕过react-hot-loader的影响(仅作测试用)
如果你暂时不想更换热加载工具,可以尝试把<BrowserRouter>移到热加载包装的外层,让路由结构避开代理组件的干扰:
import * as React from "react"; import "./index.less"; import { BrowserRouter, Route, Routes } from "react-router-dom"; import { hot } from "react-hot-loader"; import SignIn from "../sign-in"; import SignUp from "../sign-up"; // 把路由内容单独抽成组件,避免被hot包装影响 const AppContent = () => { return ( <Routes> <Route path="/" element={<SignIn />} /> <Route path="/signup" element={<SignUp />} /> </Routes> ); }; const App = () => { return ( <BrowserRouter> <AppContent /> </BrowserRouter> ); }; declare let module: Record<string, unknown>; export default hot(module)(App);
另外提个小细节:你的sign-up组件里显示的是<p>Sign In</p>,应该改成<p>Sign Up</p>哦,不过这和路由错误无关~
内容的提问来源于stack exchange,提问作者Natheeshkumar Rangasamy
相关产品推荐
相关产品推荐

