由于 React 没有专用的 @esmx/router 集成包,你需要使用标准 React 模式实现自己的 hooks 和上下文提供者。本页文档记录了 useRouter()、useRoute() 和 RouterProvider 的推荐实现。
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>
);
}RouterError — 如果在 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>
);
}RouteError — 如果在 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
);
}