0.1.0 • Published 5 months ago

pure-react-router v0.1.0

Weekly downloads
-
License
ISC
Repository
github
Last release
5 months ago

Pure React Router

NPM Downloads version npm bundle size (version) NPM Last Update GitHub commit activity

基于 React 的 超轻量 路由库,参考了 React Router 但大幅精简了 API。

介绍

特性

  • ✈️ 极致轻量 - 压缩后仅 1.2kb,除宿主自带 React 外,零第三方依赖
  • ♻️ 平滑迁移 - 兼容 React Router 核心 API
  • 🚀 未来无忧 - 专注路由核心功能,拒绝框架膨胀
  • TypeScript 优先 - 完整的类型定义支持

为什么要有 Pure React Router?

每次创建新项目时,我一般习惯将基础依赖如 React、React Router 等升级到最新的稳定版本,但当我将旧的路由代码迁移到新的项目时,发现 React Router API 又发生了变更导致运行时报错 ^崩溃^

压垮骆驼的最后一根稻草,是在 React Conf 2024 上,Remix 团队宣布在即将发布的 React Router v7.0 中,将 React Router 和 Remix 进行合并,是的没看错,它正式成为了一个全栈框架。

众所周知,对于大型框架如 Next.js、Tanstack 等的路由系统为了支持复杂的功能,往往会有繁杂的 API 和不知隐藏在何处的文档,而这次,我再也不想将就了。Pure React Router 由此应运而生,你再也不用担心你的路由库会变成一个巨石框架的一部分了。

快速开始

安装

pnpm install pure-react-router
# 或
npm install pure-react-router
# 或
yarn add pure-react-router

基础示例

// 在根组件中初始化路由
import { BrowserRouter, Route } from "pure-react-router";
import Home from "./pages/Home";
import About from "./pages/About";

// 路由配置(支持树形结构)
const routes = [
  { path: "/home", component: Home },
  { path: "/about", component: About },
  { path: "/", redirect: "/home" }, // 支持重定向
];

export default function App() {
  return (
    <BrowserRouter routes={routes} basename="/webapp">
      <Route />
    </BrowserRouter>
  );
}

📚 核心 API

组件

BrowserRouter

路由容器。接收一个扁平的 routes 数组配置。

属性:

  • basename 路由前缀
  • routes 路由配置

场景应用:在应用入口文件中定义路由结构。

const RouteList = [
  { path: "/default-page", component: DefaultPage },
  { path: "/others-page", component: OthersPage },
  { path: "/", component: Test5 },
];

const App = () => {
  return (
    <BrowserRouter routes={RouteList} basename="/webapp">
      页面内容 (内部需嵌套 <Route /> 组件使用)
    </BrowserRouter>
  );
};

const root = ReactDOM.createRoot(document.getElementById("root")!);
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

Route

路由占位组件,根据路由变化自动切换渲染内容。

const App = () => {
  return (
    <BrowserRouter routes={RouteList} basename="webapp">
      {/* 页面其他部分 */}
      <OtherLayout />
      {/* 路由组件 */}
      <Route />
    </BrowserRouter>
  );
};

Link

跳转组件,用于替换 a 标签。

属性:

  • className a 标签类名,可选
  • to 目标路径(无需拼接 basename)
  • children 链接文本元素(可以是 React 组件)

场景应用:跳转到其他路由。

export default function App() {
  return (
    <Link className="text-blue" to="/test1">
      test1
    </Link>
  );
}

Hooks

useHistory

获取 history 对象。

场景应用:监听 pathname 变更修改页面标题。

import { useHistory } from "pure-react-router";
import pkgJson from "../package.json";

export default function App() {
  const history = useHistory();

  useEffect(() => {
    if (history.location.pathname.includes("detail")) {
      document.title = `详情`;
    }
    document.title = pkgJson.name;
  }, [history.location.pathname]);

  return <div>Content</div>;
}

useParams

获取 URL 中的 Path 参数。

场景应用:获取 Path 中的 id 查询详情。

示例:路由定义为 /detail/:id, 页面实际路径为 /detail/123,则 useParams() 的返回结果为 {id: '123'}

import { useState } from "react";
import { useParams } from "pure-react-router";

export default function App() {
  const params = useParams();
  const [detail, setDetail] = useState();

  const getDetail = async (id: string) => {
    const result = await promise();
    setDetail(result);
  };

  useEffect(() => {
    getDetail(params.id);
  }, []);

  return <div>{detail}</div>;
}

useSearchParams

获取 URL 中的参数,等价于 new URLSearchParams(window.location.pathname)

场景应用:获取 URLSearchParams 中的 id 查询详情。

import { useSearchParams } from "pure-react-router";

export default function App() {
  const searchParams = useSearchParams();
  const [detail, setDetail] = useState();

  const getDetail = async (id: string) => {
    const result = await promise();
    setDetail(result);
  };

  useEffect(() => {
    getDetail(searchParams.get("id"));
  }, []);

  return <div>{detail}</div>;
}

useMatchRoute

获取当前匹配的路由信息,同 matchRoute(history.location.pathname, routes)

场景应用:处理 404 页面跳转逻辑。

import {
  useMatchRoute,
  useHistory,
  PureRouterContext,
  Route,
} from "pure-react-router";

export default function App() {
  const { routes } = useContext(PureRouterContext);
  const history = useHistory();
  const { route } = useMatchRoute();

  useEffect(() => {
    if (!route) {
      history.push("/common/404");
    }
  }, [history.location.pathname]);
}

PureRouterContext

全局上下文。

场景应用:深层嵌套子组件获取 basename 配置。

import { useContext } from "react";
import { PureRouterContext } from "pure-react-router";

export default function DeepNestedComponent() {
  const { basename } = useContext(PureRouterContext);

  return <div>当前应用:{basename}</div>;
}

Utils

matchRoute

获取指定路径匹配的路由信息。

场景应用:特殊处理某个路由的渲染。

import {
  matchRoute,
  useHistory,
  PureRouterContext,
  Route,
} from "pure-react-router";

export default function App() {
  const history = useHistory();
  const { routes } = useContext(PureRouterContext);
  const { route } = matchRoute("/home", routes);

  if (history.location.pathname === "/home") {
    return <Home specialPropName="" />;
  } else {
    return <Route />;
  }
}

Types

IRoute

路由配置项。

场景应用:定义 组件的 routes 属性。

import { BrowserRouter } from "pure-react-router";

const routes: IRoute[] = [
  {
    path: "/home",
    component: Home,
  },
  {
    path: "/about",
    component: About,
  },
  {
    path: "/",
    component: Home,
  },
];

export const App = () => {
  return (
    <BrowserRouter routes={routes} basename="/webapp">
      <Route />
    </BrowserRouter>
  );
};

最佳实践

路由懒加载

pure-react-router 支持路由懒加载,只需将路由配置中的 component 属性的声明方式改为 lazy 函数即可。

要注意的是,使用 lazy 加载组件后,在 <Route /> 组件的外层需要使用 Suspense 组件包裹,否则会出现运行时报错。

import { lazy, Suspense } from 'react';

const routes = [
  {
    path: "/dashboard",
    component: lazy(() => import('./Dashboard')),
    // 支持路由级加载状态
    loading: <DashboardSkeleton />
  }
];

function App() {
  return (
    <BrowserRouter routes={routes}>
      <Suspense fallback={<GlobalLoader />}>
        <Route />
      </Suspense>
    </BrowserRouter>
  );
}

类型安全

pure-react-router 提供了完整的类型定义支持,你可以在项目中直接使用。

import type { IRoute } from 'pure-react-router';

// 类型化路由配置
const routes: IRoute[] = [
  {
    path: "/user/:id",
    component: UserPage,
  }
];
0.1.0

5 months ago

0.0.7

5 months ago

0.0.6

6 months ago

0.0.5

6 months ago

0.0.4

8 months ago

0.0.3

9 months ago

0.0.2

9 months ago

0.0.1

9 months ago