You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React模块联邦应用useNavigate()路由上下文错误求助

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:20:38