npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-router-dom

v1.0.1

Published

React Native 版 react-router-dom:基于 React Navigation 的配置式路由(Stack/Tabs/Outlet/Guard + Web linking)

Readme

react-native-router-dom

npm version license bundle size TypeScript React Navigation

English

如果你会 react-router-dom,你就已经会用这个库了。

在 React Native 上提供一套与 react-router-dom 几乎一致的 APIuseNavigateuseLocationuseParams<Link><Outlet>... 写法基本相同,零学习成本。底层自动映射到 React Navigation(Stack/Tabs),你只需关注路由配置本身。

为什么选择 react-native-router-dom?

  • 零学习成本 — API 与 react-router-dom 高度一致,会写 Web 路由就会写 RN 路由
  • 用法极简 — 一个 RouteProps[] 配置 + 一个 <RouterProvider />,三行代码接入路由
  • 心智统一 — Web 和 RN 共用一套路由写法,跨端开发无需切换思维
  • 开箱即用 — React Navigation v7 内置,无需手动配置 Navigator 树

用法对比:react-router-dom vs react-native-router-dom

react-router-dom(Web):

// 定义路由
<BrowserRouter>
  <Routes>
    <Route path="/home" element={<Home />} />
    <Route path="/user/:id" element={<User />} />
    <Route path="/settings" element={<SettingsLayout />}>
      <Route index element={<SettingsHome />} />
      <Route path="detail" element={<SettingsDetail />} />
    </Route>
  </Routes>
</BrowserRouter>

// 页面中使用
const navigate = useNavigate();
navigate('/user/42');
navigate(-1);
const { id } = useParams();
const [searchParams, setSearchParams] = useSearchParams();

react-native-router-dom(RN)— 几乎一样:

// 定义路由(配置式,更简洁)
const routes: RouteProps[] = [
  { path: '/home', element: Home },
  { path: '/user/:id', element: User },
  { path: '/settings', element: SettingsLayout, children: [
    { index: true, element: SettingsHome },
    { path: 'detail', element: SettingsDetail },
  ]},
];
<RouterProvider routes={routes} />

// 页面中使用 — 完全一样!
const navigate = useNavigate();
navigate('/user/42');
navigate(-1);
const { id } = useParams();
const [searchParams, setSearchParams] = useSearchParams();

Hooks 和组件的用法完全相同,唯一区别是路由定义从 JSX 改为配置对象——更适合 RN 的声明式场景。

核心特性

| 特性 | 说明 | |------|------| | 配置式路由 | 用 RouteProps[] 描述路由树,一份配置驱动 Stack/Tabs | | 统一跳转 | navigate('/settings/detail') 可跨 Tabs/嵌套栈直达 | | 嵌套路由 | <Outlet /> + index route,与 react-router 一致 | | 路由守卫 | 全局 beforeEach + 路由级 guard,支持 async | | 错误边界 | errorFallback / RouterErrorBoundary,单页崩溃不白屏 | | Web linking | 支持 history / hash 模式,地址栏直达/刷新/回退 | | TypeScript | 完整类型导出,严格类型推导 | | 零配置 | React Navigation v7 依赖内置,开箱即用 | | 极致体积 | ESM gzip ~7.3 KB,见下方体积明细 |

构建产物体积

| 产物 | 原始大小 | gzip | |------|----------|------| | dist/index.mjs (ESM) | 22.0 KB | ~7.3 KB | | dist/index.js (CJS) | 23.5 KB | ~8.0 KB | | dist/index.d.ts (类型) | 8.5 KB | — |

以上为压缩后的实际数据(ESM Terser / CJS esbuild)。业务侧 Metro/webpack 打包时只会引入其中一种格式。

兼容性

| 平台 | 版本要求 | |------|----------| | React | >= 18.2.0 | | React Native | >= 0.72 | | React Navigation | v7(内置) | | react-native-web | 支持 | | Hermes | 支持(内置 URLSearchParams 降级) | | Expo | 支持(需 bare workflow 或 dev-client) |

安装

npm i react-native-router-dom

依赖说明

本库已内置 React Navigation 核心依赖(v7),你无需单独安装。

但你需要手动安装以下原生依赖(React Navigation 运行必需):

npm i react-native-screens react-native-safe-area-context

⚠️ 注意:安装完成后,iOS 项目请务必执行 cd ios && pod install

快速开始

1) 定义路由(routes)

import type { RouteProps } from 'react-native-router-dom';
import { Login } from './Login';
import { Home } from './Home';

export const routes: RouteProps[] = [
  { path: '/login', element: Login, options: { headerShown: false } },
  { path: '/home', element: Home, options: { title: '首页' } },
];

2) 渲染 RouterProvider

import React from 'react';
import { RouterProvider, createNativeRouter } from 'react-native-router-dom';
import { routes } from './routes';

export default function App() {
  const router = React.useMemo(() => createNativeRouter(routes), []);
  return <RouterProvider router={router} />;
}

核心概念(强烈建议先看)

RouteProps(路由配置)

RouteProps 是你唯一需要维护的路由“真相来源”。它会被映射成 React Navigation 的一棵 Navigator 树。

类型:

type RouteType = 'stack' | 'tabs';

type RouteMeta = Record<string, unknown>;

type RouteElement = React.ComponentType<any> | React.ReactElement | null;

type RouteProps = {
  path?: string;
  index?: boolean;
  element?: RouteElement;
  children?: RouteProps[];
  type?: RouteType;
  navigatorOptions?: any;
  options?: any;
  meta?: RouteMeta;
  guard?: RouteGuard;
};

关键字段:

  • path:
    • 绝对 path:以 / 开头,例如 /settings/detail
    • 相对 path:不以 / 开头,例如 detail,会拼接到父路由 path 后
    • 通配:/docs/*(匹配任意后续片段)
    • 动态参数:/user/:id
  • index:对齐 react-router 的 index route(匹配父路由的 path;此时 path 可省略)
  • element:页面组件(ComponentType / ReactElement / null)
  • children:嵌套路由
  • type:
    • 'tabs':该节点的 children 会被渲染为 Tab.Navigator
    • 'stack'(默认):该节点的 children 会被渲染为 Stack.Navigator
  • meta:任意元信息(常用于 Guard)
  • guard:路由级守卫(从父到子依次执行)
  • navigatorOptions:React Navigation Navigator 级 props(原样透传到 Tab.Navigator / Stack.Navigator)
  • options:React Navigation Screen options(原样透传到 Tab.Screen / Stack.Screen)

重要约束:

  • leaf route(没有 children 的路由)必须有 element,否则会在启动时抛错

路由构建规则(理解这些能少踩坑)

  • 每个非 index route 必须提供 path;否则会抛错:Route 缺 path,父:"/xxx"
  • leaf route 必须有 element;否则会抛错:Route "/xxx" 缺 element
  • index route 的“路由语义 path”会等于父路由的 path(用于匹配/生成 URL)
  • Tabs 的初始页面选择规则:优先选择第一个非 index 子路由
  • Stack 的初始页面选择规则:优先选择第一个 index 子路由
  • 内部会为每个 route 生成全局唯一的 screenName;当配置导致 screenName 冲突时会抛错:重复 screenName:xxx

Tabs/Stack 的 React Navigation 参数透传(与官方 API 对齐)

为了避免“改一个 TabBar 样式就要改源码发包”,本库将 React Navigation 的参数分成两层透传:

  • Navigator 级:用 navigatorOptions,会原样透传到 Tab.Navigator / Stack.Navigator
  • Screen 级:用 options,会原样透传到 Tab.Screen / Stack.Screen

示例:调整 TabBar 图标/文字布局方向(官方 screenOptions)

import { Image } from 'react-native';
import type { RouteProps } from 'react-native-router-dom';

const Home = () => null;

export const routes: RouteProps[] = [
  {
    path: '/main',
    type: 'tabs',
    navigatorOptions: {
      screenOptions: {
        tabBarLabelPosition: 'beside-icon',
        tabBarItemStyle: { flexDirection: 'row' },
      },
    },
    children: [
      {
        path: '/home',
        element: Home,
        options: {
          title: '首页',
          tabBarLabel: '首页',
          tabBarIcon: ({ focused, size }) => (
            <Image
              source={focused ? require('./home-active.png') : require('./home.png')}
              style={{ width: size, height: size }}
              resizeMode="contain"
            />
          ),
        },
      },
    ],
  },
];

location(当前路由状态)

useLocation() 会返回当前的 RouteLocation:

  • pathname:/settings/detail
  • search:?x=1
  • hash:#top
  • params:动态参数与通配参数(:id、*)
  • matches:从父到子匹配到的 route 列表(可用于 Guard 判定)

跳转与导航

useNavigate(推荐)

import { useNavigate } from 'react-native-router-dom';

const navigate = useNavigate();

await navigate('/profile');        // 绝对跳转
await navigate('/user/42?x=1#top'); // search/hash 也会透传
await navigate(-1);                // 返回

动画与转场

本库直接复用 React Navigation 的动画能力。你不需要学习新的 API,只需要将 React Navigation 的配置写在 optionsnavigatorOptions 里即可。

1. 单个页面配置动画

RouteProps 中使用 options 字段,这相当于 <Stack.Screen options={...} />

{
  path: '/login',
  element: Login,
  options: {
    // 设为模态窗效果(从下往上弹出)
    presentation: 'modal',
    // 简单的淡入淡出
    animation: 'fade',
  },
}

2. 全局/Stack 级配置动画

RouteProps 中使用 navigatorOptions 字段,这相当于 <Stack.Navigator screenOptions={...} />

{
  path: '/', // 根路由通常是 stack
  navigatorOptions: {
    screenOptions: {
      // 让该 stack 下所有页面默认都是 slide_from_right
      animation: 'slide_from_right',
      // 统一配置头部样式
      headerStyle: { backgroundColor: 'white' },
    },
  },
  children: [
    // ... 子路由都会继承这个动画配置
  ]
}

3. 常用动画预设(Native Stack)

React Navigation 提供了丰富的预设动画(animation 属性):

  • 'default': 平台默认动画(iOS 右侧滑入,Android 底部浮现或淡入)
  • 'fade': 淡入淡出
  • 'slide_from_right': 从右侧滑入(类似 iOS 默认)
  • 'slide_from_bottom': 从底部滑入(类似 Android 默认)
  • 'simple_push': 标准 push 动画

更多高级配置(如 transitionSpec)请参考 React Navigation 文档

相对跳转说明:

  • navigate('detail') 会基于“当前 committed location.pathname”做相对解析
  • committed location 由 在导航状态变更后维护
  • 如果你在 RouterProvider ready 之前调用,可能会以 '/' 作为基准

useRouter(push/replace/back 的别名集合)

import { useRouter } from 'react-native-router-dom';

const router = useRouter();
await router.push('/home');
await router.replace('/login');
router.back();

generatePath(动态参数生成)

import { generatePath } from 'react-native-router-dom';

generatePath('/user/:id', { id: '42' }); // /user/42
generatePath('/docs/*', { '*': 'a/b' }); // /docs/a/b

组件

RouterProvider

RouterProvider 是整个路由系统的宿主,负责:

  • 持有 router 实例并通过 Context 暴露给 Hooks/Link/Navigate
  • 将 RouteProps[] 映射成 React Navigation 的 Navigator 树
  • 处理 onStateChange,运行 Guard,并维护当前 committed location
  • 在 Web 端连接 React Navigation linking 与浏览器地址栏

类型:

import type { RouterProviderProps } from 'react-native-router-dom';

type RouterProviderProps = {
  /** 已创建好的 Router;与 routes 互斥,优先使用该值 */
  router?: NativeRouter;
  /** 路由配置;不传 router 时必传 */
  routes?: RouteProps[];
  /** 全局守卫(等价于 createNativeRouter(..., { beforeEach })) */
  beforeEach?: RouteGuard;
  /** 路由页面渲染出错时展示的 UI 或 (error, reset) => ReactNode,防止整应用白屏 */
  errorFallback?: React.ReactNode | ((error: Error, reset: () => void) => React.ReactNode);
  /** 路由错误回调,可用于上报 */
  onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
  /** 自定义 React Navigation linking;不传时会自动基于 routes 生成 */
  linking?: any;
  /** linking 前缀,仅在 linking 未传时生效,例如 ['https://example.com'] */
  prefixes?: string[];
  /**
   * Web 路由模式(只在 linking 未传时生效)
   * - 'history': HTML5 History(默认)
   * - 'hash': Hash 模式(#/path)
   */
  linkingType?: 'history' | 'hash';
};

用法示例:直接传 routes(简单场景推荐):

import { RouterProvider } from 'react-native-router-dom';
import { routes } from './routes';

export default function App() {
  return <RouterProvider routes={routes} />;
}

用法示例:显式创建 router(方便做 SSR 或测试):

import React from 'react';
import { RouterProvider, createNativeRouter } from 'react-native-router-dom';
import { routes } from './routes';

export default function App() {
  const router = React.useMemo(() => createNativeRouter(routes, { beforeEach }), []);
  return <RouterProvider router={router} />;
}

Outlet(嵌套路由)

  • 父路由 element 中渲染 ,子路由页面会在 Outlet 位置渲染
  • + useOutletContext() 传递布局上下文

类型:

type OutletProps = {
  /** 传给子路由的上下文数据,useOutletContext<T>() 可获取 */
  context?: unknown;
};

用法示例:布局向子页面透传数据:

import { Outlet, useOutletContext } from 'react-native-router-dom';

function SettingsLayout() {
  const user = { name: 'Alice' };
  return <Outlet context={user} />;
}

function SettingsDetail() {
  const user = useOutletContext<{ name: string }>();
  return <Text>当前用户:{user.name}</Text>;
}

Link / NavLink

import { Link, NavLink } from 'react-native-router-dom';

<Link to="/settings">去设置</Link>

<NavLink to="/home">
  {({ isActive }) => (isActive ? '当前页' : '去首页')}
</NavLink>

LinkProps:

import type { PressableProps } from 'react-native';

type LinkProps = Omit<PressableProps, 'children'> & {
  /** 目标路径,支持绝对/相对、search、hash 等 */
  to: string;
  /** 是否使用 replace 语义(默认 push) */
  replace?: boolean;
  /** 额外透传给导航参数(会进入 React Navigation route.params) */
  params?: Record<string, any>;
  /** 渲染内容,通常是 Text 或 View */
  children?: React.ReactNode;
};

NavLinkProps:

type NavLinkProps = Omit<LinkProps, 'children' | 'style'> & {
  /** 是否使用“完全匹配”模式(类似 react-router 的 end) */
  end?: boolean;
  /** 支持函数 children,便于按 active 状态定制样式 */
  children?: React.ReactNode | ((args: { isActive: boolean }) => React.ReactNode);
  /** 支持函数 style,便于按 active 状态定制样式 */
  style?: StyleProp<ViewStyle> | ((args: { isActive: boolean }) => StyleProp<ViewStyle>);
};

NavLink style 函数示例:

<NavLink
  to="/home"
  style={({ isActive }) => ({
    backgroundColor: isActive ? '#e0e0e0' : 'transparent',
    padding: 12,
    borderRadius: 8,
  })}
>
  <Text>首页</Text>
</NavLink>

NavLink 的 isActive 规则:

  • end=true:仅当 current === target 时 active
  • end=false(默认):current === target 或 current 以 ${target}/ 开头时 active
  • target 为相对路径时,会基于当前 pathname 解析后再判断

Navigate(声明式跳转)

import { Navigate } from 'react-native-router-dom';

export function Jump() {
  return <Navigate to="/home" replace />;
}

类型:

type NavigateProps = {
  /** 目标路径,支持绝对/相对、search、hash 等 */
  to: string;
  /** 是否 replace 当前历史记录(默认 false,即 push) */
  replace?: boolean;
  /** 透传给目标页面的 params(React Navigation route.params) */
  params?: Record<string, any>;
};

Navigate 本质上是一个副作用组件:

  • 渲染时立即调用 useNavigate() 触发跳转,并返回 null
  • 常用于 routes 配置里作为 element,或某些中转页面

Hooks(API 参考)

useNativeRouter

const router = useNativeRouter();
  • 只能在 内使用,否则会抛错
  • 返回 NativeRouter 实例,包含:
    • routes:当前 RouteProps[]
    • navigationRef:React Navigation 的 NavigationContainerRef
    • beforeEach(fn):注册全局守卫,返回取消函数
    • navigate(to, options?) / push(to, params?) / replace(to, params?) / back()
    • getCurrentLocation()

适合做一些底层集成场景,例如自定义返回行为等。

useRouter

const { push, replace, back, navigate } = useRouter();
  • 是对 useNativeRouter 的“瘦包装”,只暴露最常用的导航方法
  • 适用于大多数业务组件

useNavigate

const navigate = useNavigate();

await navigate('/profile');
await navigate(-1); // 返回
await navigate('/user/42?x=1#top', { replace: true, params: { from: 'home' } });

签名:

type NavigateFn = (to: string | number, options?: NavigateOptions) => Promise<boolean>;

type NavigateOptions = {
  replace?: boolean;
  params?: Record<string, any>;
};
  • to 为 number 且 < 0 时等价于 back()
  • 返回 Promise,表示是否成功触发导航(未匹配到路由、NavigationContainer 未 ready 等情况会返回 false)

useLocation

const location = useLocation();
// location: RouteLocation | null

RouteLocation 结构:

type RouteLocation = {
  pathname: string;
  search: string;
  hash: string;
  params: Record<string, string>;
  matches: RouteMatch[];
};

RouteMatch:

type RouteMatch = {
  route: RouteProps;
  pathname: string;
  params: Record<string, string>;
};

useParams

const params = useParams(); // Record<string, string>
const id = params.id;
const rest = params['*']; // 对应通配符 /docs/*
  • 来源于当前匹配到的 leaf route 的动态参数与通配符参数

useSearchParams

const [searchParams, setSearchParams] = useSearchParams({ page: '1' });

const page = searchParams.get('page'); // string | null

setSearchParams({ page: '2' }); // ?page=2
setSearchParams('page=3&sort=desc', { replace: true });

签名:

function useSearchParams(
  defaultInit?: string | Record<string, string>,
): [
  SearchParamsLike,
  (nextInit: string | Record<string, string> | SearchParamsLike, options?: { replace?: boolean }) => void,
];

type SearchParamsLike = {
  get: (name: string) => string | null;
  has: (name: string) => boolean;
  set: (name: string, value: string) => void;
  delete: (name: string) => void;
  entries: () => IterableIterator<[string, string]>;
  toString: () => string;
};
  • 返回的 SearchParamsLike 在有 URLSearchParams 的环境(Web)中直接使用原生实现,在 Hermes 等没有 URLSearchParams 的环境中自动降级为内置的轻量实现
  • defaultInit 仅在当前 search 没有某个 key 时作为默认值写入
  • setSearchParams 会基于当前 pathname/hash 生成新 URL,并通过 navigate 跳转

useMatch

const match = useMatch('/settings/*');
// match: { pathname, params, pattern } | null
  • pattern 支持动态参数与通配符,语义与 RouteProps.path 一致
  • 典型用途:根据某个子路由是否匹配来高亮菜单等

useBlocker(阻止导航)

import { useBlocker } from 'react-native-router-dom';

// 布尔值形式:有未保存内容时阻止离开
useBlocker(hasUnsavedChanges);

// 函数形式:根据目标路由决定是否阻止
useBlocker(({ to }) => to.pathname !== '/save-confirm' && hasUnsavedChanges);

签名:

type BlockerFunction = (ctx: RouteGuardContext) => boolean;

function useBlocker(blocker: BlockerFunction | boolean): void;
  • 返回 true 表示阻止导航,false 表示放行
  • 内部通过 beforeEach 实现,组件卸载时自动取消注册
  • 典型场景:表单编辑页、文档编辑页等需要防止意外离开的页面

useInRouterContext

const inContext = useInRouterContext(); // boolean
  • <RouterProvider /> 内为 true,否则为 false,可用于条件渲染或降级逻辑

useOutletContext

const ctx = useOutletContext<{ name: string }>();
  • 获取父级 Outlet 通过 context 传下来的数据

Guard(路由守卫)

Guard 支持两层:

  1. 全局:router.beforeEach(fn) 或 createNativeRouter(routes, { beforeEach: fn })
  2. 路由级:route.guard

执行顺序:

  • 先执行所有 beforeEach(按注册顺序)
  • 再从父到子依次执行 matches 中每个 route.guard

返回值语义:

  • true / void:放行
  • false:拦截(停留在原页面;Tab 点击会被阻止并回滚)
  • string:重定向到该 path(默认 replace)
  • redirect(to, { replace? }):更显式的重定向对象

类型:

type RouteGuardContext = {
  to: RouteLocation;
  from: RouteLocation | null;
};

type RouteGuardResult = boolean | Redirect | string | void;

type RouteGuard = (
  ctx: RouteGuardContext,
) => RouteGuardResult | Promise<RouteGuardResult>;

示例:

import { redirect } from 'react-native-router-dom';

router.beforeEach(({ to }) => {
  const requiresAuth = to.matches.some(m => (m.route.meta as any)?.requiresAuth);
  if (!requiresAuth) return true;
  return redirect('/login');
});

示例:注册/取消注册 beforeEach

const dispose = router.beforeEach(async ({ to }) => {
  if (to.pathname === '/login') return true;
  return true;
});

dispose();

示例:路由级 guard(只对该分支生效)

import { redirect, type RouteProps } from 'react-native-router-dom';

export const routes: RouteProps[] = [
  {
    path: '/guarded',
    element: GuardedPage,
    guard: async ({ to }) => {
      if (await isLoggedIn()) return true;
      return redirect('/login', { replace: true });
    },
  },
];

Web linking(react-native-web)

RouterProvider 在 web 上会通过 React Navigation linking 与地址栏同步:

  • history 模式(默认):
    • 支持地址栏直达:直接访问 /settings/detail
    • 支持刷新:刷新后仍停留在对应页面
    • 支持回退:浏览器 back/forward 与导航状态同步
    • 要求 dev server 开启 history fallback(例如 webpack-dev-server 的 historyApiFallback: true)
  • hash 模式:
    • URL 形如 http://localhost:8080/#/settings/detail
    • 不依赖 history fallback(因为路径在 hash 里)
    • 通过 RouterProvider 内部同步地址栏,避免 React Navigation 在 web 下重复拼接 hash

要点:

  • 如果你需要自定义 scheme/prefix,可以用 createLinking(routes, { prefixes }) 并传给 RouterProvider 的 linking
  • 如果你需要 hash 模式:<RouterProvider linkingType="hash" ... />

Demo(建议作为“可运行文档”使用)

目录:demo/

运行:

cd demo
npm i

# iOS / Android
npm run ios
npm run android

# Web
npm run web

demo 覆盖的验证路由(建议在 web 下逐个用地址栏直达 + 刷新验证):

  • /home:Link/NavLink、useRouter、generatePath、跨 Tab/嵌套跳转
  • /settings:Outlet + index route、useMatch、useOutletContext、useSearchParams
  • /settings/detail:相对跳转(..)、navigate(-1)、Guard(需要登录)
  • /params:useLocation/useSearchParams 示例
  • /user/:id:useParams 动态参数
  • /docs/:useParams()[''] 通配
  • /guarded:route.guard 示例
  • /jump: 示例(带 query/hash)
  • /blocker:useBlocker 示例(未保存离开拦截)

导出 API(总览)

createNativeRouter

import { createNativeRouter } from 'react-native-router-dom';

const router = createNativeRouter(routes, {
  beforeEach: async ({ to, from }) => {
    // 可做登录校验、埋点等
    return true;
  },
});

签名:

type CreateNativeRouterOptions = {
  beforeEach?: RouteGuard;
};

function createNativeRouter(
  routes: RouteProps[],
  options?: CreateNativeRouterOptions,
): NativeRouter;

NativeRouter 关键字段:

  • routes: RouteProps[]
  • navigationRef: NavigationContainerRefWithCurrent
  • beforeEach(guard: RouteGuard): () => void
  • navigate(to: string | number, options?: NavigateOptions): Promise
  • push(to: string, params?: Record<string, any>): Promise
  • replace(to: string, params?: Record<string, any>): Promise
  • back(): void
  • getCurrentLocation(): RouteLocation | null

一般业务只需要通过 RouterProvider + Hooks/Link 使用;直接操作 NativeRouter 适合做底层集成。

createLinking

import { createLinking } from 'react-native-router-dom';

const linking = createLinking(routes, {
  prefixes: ['https://example.com', 'myapp://'],
});

<RouterProvider routes={routes} linking={linking} />;

签名:

type LinkingOptions = {
  prefixes?: string[];
};

function createLinking(routes: RouteProps[], options?: LinkingOptions): {
  prefixes: string[];
  config: { screens: Record<string, any> };
};
  • 默认 prefixes 为 [''],即可直接用 /path 形式的 URL
  • config.screens 结构与 React Navigation linking config 一致

redirect / isRedirect

import { redirect, isRedirect } from 'react-native-router-dom';

router.beforeEach(({ to }) => {
  if (to.pathname.startsWith('/admin') && !isAdmin()) {
    return redirect('/login', { replace: true });
  }
});

签名:

type Redirect = {
  type: 'redirect';
  to: string;
  replace?: boolean;
};

function redirect(to: string, options?: { replace?: boolean }): Redirect;
function isRedirect(value: unknown): value is Redirect;

generatePath

import { generatePath } from 'react-native-router-dom';

const url = generatePath('/user/:id', { id: user.id });
// /user/123

签名:

function generatePath(pattern: string, params?: Record<string, any>): string;
  • pattern 支持 :id、:slug 和 * 通配符

RouterErrorBoundary

import { RouterErrorBoundary } from 'react-native-router-dom';

<RouterErrorBoundary fallback={<Text>出错了</Text>} onError={(err) => log(err)}>
  {children}
</RouterErrorBoundary>
  • 用于包裹需要隔离错误的路由子树;未传 errorFallback/onError 时,RouterProvider 不会为每个路由包裹错误边界

类型导出(TypeScript)

常用类型:

  • RouteProps:路由配置
  • RouteType:'stack' | 'tabs'
  • RouteMeta:Record<string, unknown>
  • RouteGuard / RouteGuardContext / RouteGuardResult
  • Redirect
  • RouteLocation / RouteMatch
  • SearchParamsLike:useSearchParams 返回的搜索参数对象类型
  • BlockerFunction:useBlocker 的回调函数类型

所有类型均从包入口导出,可直接:

import type {
  RouteProps,
  RouteLocation,
  RouteMatch,
  RouteGuard,
  RouteGuardContext,
} from 'react-native-router-dom';

在业务项目中,推荐尽量使用这些类型而不是自己手写结构,以便在库升级时获得更好的类型兼容性。

react-router-dom 功能对照

| react-router-dom | react-native-router-dom | 说明 | |-------------------|--------------------------|------| | BrowserRouter / MemoryRouter | RouterProvider | 配置式入口 | | <Routes> / <Route> | RouteProps[] | 配置驱动,无 JSX 路由 | | <Link> / <NavLink> | <Link> / <NavLink> | 行为一致 | | <Navigate> | <Navigate> | 声明式跳转 | | <Outlet> | <Outlet> | 嵌套路由出口 | | useNavigate | useNavigate | 编程式导航 | | useLocation | useLocation | 当前位置 | | useParams | useParams | 动态参数 | | useSearchParams | useSearchParams | 查询参数(含 Hermes 降级) | | useMatch | useMatch | 路径匹配 | | useOutletContext | useOutletContext | Outlet 上下文 | | useBlocker | useBlocker | 导航拦截 | | useInRouterContext | useInRouterContext | 是否在路由上下文 | | generatePath | generatePath | 路径生成 | | — | beforeEach / guard | 路由守卫(RR 无对应) | | — | RouterErrorBoundary | 路由级错误边界 | | — | createLinking | Deep linking 配置 |

Contributing

欢迎提交 Issue 和 PR。开发流程:

git clone https://gitee.com/ws18250840411/react-native-router-dom.git
cd react-native-router-dom
npm i
npm run typecheck   # 类型检查
npm run build       # 构建

cd demo
npm i
npm test            # 运行测试
npm run ios         # 运行 Demo

License

MIT