React模块联邦应用useNavigate()路由上下文错误求助
问题描述
构建React模块联邦应用时,主应用的HomePageComponent组件调用useNavigate()时触发错误:
useNavigate() may be used only in the context of a
component
已在App.jsx通过RouterProvider配置路由,且组件属于主应用,怀疑问题与模块联邦配置相关。
相关代码
App.jsx
import './App.css'; import React from 'react'; import ReactDOM from 'react-dom/client'; import reportWebVitals from './reportWebVitals'; import { SnackbarProvider } from "notistack"; import routes from "./routes"; import { createBrowserRouter, BrowserRouter as Router, RouterProvider, useRoutes } from 'react-router-dom'; const router = createBrowserRouter(routes) function App() { return ( <RouterProvider router={createBrowserRouter(routes)}> </RouterProvider> ); } const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <SnackbarProvider preventDuplicate anchorOrigin={{ vertical: "top", horizontal: "center", }} maxSnack={3} > <App /> </SnackbarProvider> </React.StrictMode> ); reportWebVitals(); export default App;
routes.js
import UnAuthorizedLayout from "./layout/UnAuthorized"; import Authentication from "./components/forms/Authentication"; import HomePageLayout from "./layout/HomePageLayout"; const routes = [ { path: '/', element: <UnAuthorizedLayout />, children: [ { path: '/', element: <Authentication /> } ] }, { path: '/dashboard', element: <LoggedInLayout />, children: [ { path: '/dashboard', element: <HomePageLayout /> } ] }, { path: '*', element: <> <h1>404</h1> </> } ]; export default routes;
HomeComponent/index.js
import { Paper } from '@mui/material'; import * as React from 'react'; import { useNavigate } from 'react-router'; const HomePageComponent = () => { const theme = useTheme(); // ... 其他逻辑 const navigate = useNavigate(); React.useEffect(() => { // ... 其他逻辑 if (!userDetails) { navigate("/", { replace: true }); } // ... 其他逻辑 }, [navigate, userDetails]) return ( <Paper style={{ padding: '1rem', margin: '1rem', }} elevation={1}> {/* ... 组件内容 */} </Paper> ) } export default HomePageComponent;
排查与解决方法
1. 修复路由上下文传递问题
你的App.jsx中RouterProvider未包裹任何子组件,导致路由上下文无法向下传递。修改App.jsx,确保路由组件在RouterProvider的上下文范围内:
function App() { // 复用路由实例,避免重复创建 const router = createBrowserRouter(routes); // 或者使用useRoutes渲染路由元素 const routeElement = useRoutes(routes); return ( <RouterProvider router={router}> {routeElement} </RouterProvider> ); }
2. 配置模块联邦共享依赖
模块联邦若未共享路由相关依赖,会导致主/远程应用加载多份react-router-dom实例,造成上下文隔离。在主应用的webpack.config.js中配置共享依赖并开启单例模式:
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); module.exports = { plugins: [ new ModuleFederationPlugin({ name: 'host', remotes: { // 你的远程应用配置 }, shared: { react: { singleton: true, eager: true }, 'react-dom': { singleton: true, eager: true }, 'react-router-dom': { singleton: true, eager: true }, }, }), ], };
singleton: true确保全局仅存在一份依赖实例,eager: true避免异步加载导致的上下文丢失。
3. 检查布局组件的Outlet配置
确认LoggedInLayout组件包含Outlet,用于渲染子路由(HomePageLayout),否则子组件无法纳入路由上下文:
import { Outlet } from 'react-router-dom'; const LoggedInLayout = () => { return ( <div> {/* 布局头部/侧边栏等内容 */} <Outlet /> {/* 子路由组件会在此处渲染 */} </div> ); };
4. 修正useNavigate的导入路径
HomePageComponent中错误导入了react-router的useNavigate,应从react-router-dom导入:
// 错误 import { useNavigate } from 'react-router'; // 正确 import { useNavigate } from 'react-router-dom';
5. 验证路由配置的正确性
检查routes.js中LoggedInLayout是否已正确导入(当前代码中未导入,会导致渲染失败):
// 补充导入 import LoggedInLayout from "./layout/LoggedInLayout"; const routes = [ // ... 其他路由 { path: '/dashboard', element: <LoggedInLayout />, children: [ { path: '/dashboard', element: <HomePageLayout /> } ] }, ];
内容的提问来源于stack exchange,提问作者Naman Khater
相关产品推荐
相关产品推荐

