React Router从外部npm包导入路由集合及相关报错解决方案
问题解决方案
报错原因
- 第一个
Error: Invariant failed: You should not use <Route> outside a <Router>:你在npm包中直接提前实例化了<Route>组件,此时组件不在Router上下文环境中,若npm包单独安装了react-router-dom依赖,还会存在多版本react-router-dom副本,上下文完全不连通导致报错。 - 第二个「Spread children are not supported in React」:数组不能直接作为展开项传入JSX children,该语法本身不符合React规范。
修复方案
第一步:修改npm包侧代码
- 调整依赖声明:将package.json中的react-router-dom从
dependencies移动到peerDependencies,确保和主项目使用同一份路由库实例,示例配置:
{ "peerDependencies": { "react": "^17.0.0 || ^18.0.0", "react-router-dom": "^5.3.0" } }
- 改为导出纯路由配置对象,不要提前实例化
<Route>组件:
包内routes文件代码:
import Login from "./pages/login/Login"; import ForgotPassword from "./pages/forgotPassword/ForgotPassword"; import MyProfile from "./pages/myProfile/MyProfile"; export const routeConfigs = [ { exact: true, path: "/Login", component: Login }, { exact: true, path: "/ForgotPassword", component: ForgotPassword }, { exact: true, path: "/MyProfile", component: MyProfile } ]; // 可选:封装成统一路由组件,主项目可直接调用 export const PortalRoutes = () => { return ( <> {routeConfigs.map((route, idx) => ( <Route key={idx} {...route} /> ))} </> ); };
- 包入口文件调整导出:
export { routeConfigs, PortalRoutes } from "./routes"; export { Login } from "./pages/login/Login";
第二步:修改主项目代码
选择任意一种方式渲染路由即可:
方式1:使用导出的配置对象自行渲染
import { Suspense, lazy } from "react"; import { HashRouter as Router, Switch, Route } from "react-router-dom"; import { routeConfigs as PortalFrameworkRouteConfigs, Login} from "@sal/portal"; const home = lazy(() => import("./pages/home/Home")); const search = lazy(() => import("./pages/search/Search")); function AppRoutes() { return ( <Router basename="/"> <Suspense fallback={<div>Loading...</div>}> <Switch> {PortalFrameworkRouteConfigs.map((route, idx) => ( <Route key={idx} {...route} /> ))} <Route exact path="/" component={home} /> <Route exact path="/search" component={search} /> </Switch> </Suspense> </Router> ); } export default AppRoutes;
方式2:直接使用npm包封装好的路由组件(更省心,后续包新增路由主项目无需任何修改)
import { Suspense, lazy } from "react"; import { HashRouter as Router, Switch, Route } from "react-router-dom"; import { PortalRoutes, Login} from "@sal/portal"; const home = lazy(() => import("./pages/home/Home")); const search = lazy(() => import("./pages/search/Search")); function AppRoutes() { return ( <Router basename="/"> <Suspense fallback={<div>Loading...</div>}> <Switch> <PortalRoutes /> <Route exact path="/" component={home} /> <Route exact path="/search" component={search} /> </Switch> </Suspense> </Router> ); } export default AppRoutes;
内容的提问来源于stack exchange,提问作者Albert
相关产品推荐
相关产品推荐

