logo
  • 指南
  • API
  • 博客
  • 简体中文
    • 简体中文
    • English
    • @esmx/core
      Esmx
      App
      RenderContext
      ModuleConfig
      PackConfig
      ManifestJson
      @esmx/router
      Router
      Route
      路由配置
      RouterLink
      导航守卫
      动态路由匹配
      嵌套路由
      编程式导航
      滚动行为
      图层路由
      微应用
      错误类型
      类型参考
      @esmx/router-vue
      RouterPlugin
      组合式函数
      组件
      类型增强
      @esmx/router-react
      微应用集成
      Hooks 与上下文
      组件
      SSR
      App
      @esmx/rspack
      @esmx/rspack-vue
      @esmx/rspack-react

      最后更新于: 2026/4/7 02:16:07

      上一页微应用集成下一页组件

      #Hooks 与上下文

      #简介

      由于 React 没有专用的 @esmx/router 集成包,你需要使用标准 React 模式实现自己的 hooks 和上下文提供者。本页文档记录了 useRouter()、useRoute() 和 RouterProvider 的推荐实现。

      #RouterProvider

      • Props:
        • router: Router — 要提供的路由实例
        • children: React.ReactNode — 子组件
      • 返回值:JSX.Element

      上下文提供者组件,使路由实例可通过 useRouter() 和 useRoute() 供所有后代组件使用。

      import { createContext } from 'react';
      import type { Router } from '@esmx/router';
      
      const RouterContext = createContext<Router | null>(null);
      
      export function RouterProvider({
          router,
          children
      }: {
          router: Router;
          children: React.ReactNode;
      }) {
          return (
              <RouterContext.Provider value={router}>
                  {children}
              </RouterContext.Provider>
          );
      }

      #useRouter()

      • 返回值:Router
      • 异常:Error — 如果在 RouterProvider 外部调用

      通过 React context 获取路由实例。等同于 @esmx/router-vue 中的 useRouter()。

      import { useContext } from 'react';
      import type { Router } from '@esmx/router';
      
      export function useRouter(): Router {
          const router = useContext(RouterContext);
          if (!router) {
              throw new Error('useRouter 必须在 RouterProvider 内部使用');
          }
          return router;
      }

      #用法

      function NavigationButtons() {
          const router = useRouter();
      
          return (
              <div>
                  <button onClick={() => router.push('/home')}>首页</button>
                  <button onClick={() => router.back()}>返回</button>
              </div>
          );
      }

      #useRoute()

      • 返回值:Route
      • 异常:Error — 如果在 RouterProvider 外部调用

      获取当前的响应式路由对象。使用 useSyncExternalStore 实现最佳 React 集成 —— 路由变化时组件自动重新渲染。等同于 @esmx/router-vue 中的 useRoute()。

      import { useSyncExternalStore } from 'react';
      import type { Route } from '@esmx/router';
      
      export function useRoute(): Route {
          const router = useRouter();
      
          return useSyncExternalStore(
              (callback) => router.afterEach(callback),
              () => router.route,
              () => router.route
          );
      }

      #用法

      function CurrentPath() {
          const route = useRoute();
      
          return (
              <div>
                  <p>路径:{route.path}</p>
                  <p>参数:{JSON.stringify(route.params)}</p>
                  <p>查询:{JSON.stringify(route.query)}</p>
              </div>
          );
      }

      #完整实现

      组合所有 hooks 和提供者的完整参考实现:

      import { createContext, useContext, useSyncExternalStore } from 'react';
      import type { Router, Route } from '@esmx/router';
      
      // Context
      const RouterContext = createContext<Router | null>(null);
      
      // Provider
      export function RouterProvider({
          router,
          children
      }: {
          router: Router;
          children: React.ReactNode;
      }) {
          return (
              <RouterContext.Provider value={router}>
                  {children}
              </RouterContext.Provider>
          );
      }
      
      // Hooks
      export function useRouter(): Router {
          const router = useContext(RouterContext);
          if (!router) {
              throw new Error('useRouter 必须在 RouterProvider 内部使用');
          }
          return router;
      }
      
      export function useRoute(): Route {
          const router = useRouter();
      
          return useSyncExternalStore(
              (callback) => router.afterEach(callback),
              () => router.route,
              () => router.route
          );
      }