---
title: router
sidebar_position: 1
---
# router

:::info 补充信息
基于 [react-router](https://reactrouter.com/) 的路由解决方案。

:::

## hooks

### useNavigate

```ts
declare function useNavigate(): NavigateFunction;

interface NavigateFunction {
  (
    to: To,
    options?: {
      replace?: boolean;
      state?: any;
      relative?: RelativeRoutingType;
    },
  ): void;
  (delta: number): void;
}
```

`useNavigate` 返回一个可以用于执行导航操作的函数。

```tsx
import { useNavigate } from '@modern-js/runtime/router';

export function HomeButton() {
  let navigate = useNavigate();

  function handleClick() {
    navigate('/home');
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}
```

### useLocation

```ts
declare function useLocation(): Location;

interface Location extends Path {
  state: unknown;
  key: Key;
}
```

`useLocation` 返回当前 url 对应的 [location](https://reactrouter.com/web/api/location) 对象。每当路由更新的时候，都会拿到一个新的 `location` 对象。

```ts
import { useLocation } from "@modern-js/runtime/router";

function usePageViews() {
  let location = useLocation();
  React.useEffect(() => {
    ga.send(["pageview", location.pathname]);
  }, [location]);
}

function App() {
  usePageViews();
  return (
    //...
  );
}
```

### useParams

```ts
declare function useParams<K extends string = string>(): Readonly<Params<K>>;
```

`useParams` 返回一个 key/value 的键值对，表示当前匹配的路由 `<Route path>` 中的参数信息。

```tsx
import { Switch, Route, useParams } from '@modern-js/runtime/router';

function BlogPost() {
  const { slug } = useParams();
  return <div>Now showing post {slug}</div>;
}

function App() {
  return (
    <Routes>
      <Route path="/" element={<div>home</div>} />
      <Route path="/blog/:slug" element={<BlogPost />} />
    </Routes>
  );
}
```

### useRouteError

```ts
export declare function useRouteError(): unknown;
```

`useRouteError` 返回离 ErrorBoundary 定义最近的路由渲染错误信息。

```tsx
import { useRouteError } from '@modern-js/runtime/router';
const ErrorBoundary = () => {
  const error = useRouteError();
  return (
    <div>
      <h1>{error.status}</h1>
      <h2>{error.message}</h2>
    </div>
  );
};
export default ErrorBoundary;
```

## 组件

### Link

```ts
declare function Link(props: LinkProps): React.ReactElement;

interface LinkProps
  extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
  replace?: boolean;
  state?: any;
  to: To;
  reloadDocument?: boolean;
}

type To = string | Partial<Path>;
```

可以使用 `Link` 组件进行路由跳转。

```ts
<Link to="/about">About</Link>
```

### NavLink

```ts
declare function NavLink(props: NavLinkProps): React.ReactElement;

interface NavLinkProps
  extends Omit<LinkProps, 'className' | 'style' | 'children'> {
  caseSensitive?: boolean;
  children?:
    | React.ReactNode
    | ((props: { isActive: boolean }) => React.ReactNode);
  className?: string | ((props: { isActive: boolean }) => string | undefined);
  end?: boolean;
  style?:
    | React.CSSProperties
    | ((props: { isActive: boolean }) => React.CSSProperties);
}
```

`<NavLink>` 是一种特殊的 `<Link>`，当 `<NavLink>` 对应的链接和当前 URL 匹配时，会给 `<NavLink>` 所渲染的元素添加“激活”态样式。

### Outlet

```ts
interface OutletProps {
  context?: unknown;
}
declare function Outlet(props: OutletProps): React.ReactElement | null;
```

`<Outlet>` 用于嵌套路由场景。在父路由的元素中使用，代表待渲染的子路由的元素在父组件中的位置。

```tsx
function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>

      {/* This element will render either <DashboardMessages> when the URL is
          "/messages", <DashboardTasks> at "/tasks", or null if it is "/"
      */}
      <Outlet />
    </div>
  );
}

function App() {
  return (
    <Routes>
      <Route path="/" element={<Dashboard />}>
        <Route path="messages" element={<DashboardMessages />} />
        <Route path="tasks" element={<DashboardTasks />} />
      </Route>
    </Routes>
  );
}
```

### Route

```ts
interface RouteObject {
  path?: string;
  index?: boolean;
  children?: React.ReactNode;
  caseSensitive?: boolean;
  id?: string;
  loader?: LoaderFunction;
  action?: ActionFunction;
  element?: React.ReactNode | null;
  errorElement?: React.ReactNode | null;
  handle?: RouteObject['handle'];
  shouldRevalidate?: ShouldRevalidateFunction;
}
```

`Route` 用于定义路由。一个 `Route` 对象，将 URL 片段和组件、数据获取关联起来。

`Route` 可以作为普通对象，传给创建 router 的函数的参数：

```ts
const router = createBrowserRouter([
  {
    // it renders this element
    element: <Team />,

    // when the URL matches this segment
    path: 'teams/:teamId',

    // with this data loaded before rendering
    loader: async ({ request, params }) => {
      return fetch(`/fake/api/teams/${params.teamId}.json`, {
        signal: request.signal,
      });
    },

    // performing this mutation when data is submitted to it
    action: async ({ request }) => {
      return updateFakeTeam(await request.formData());
    },

    // and renders this element in case something went wrong
    errorElement: <ErrorBoundary />,
  },
]);
```

`Route` 还可以作为组件使用，通过 `createRoutesFromElements` 转换后，再传给创建 router 的函数的参数：

```ts
const router = createBrowserRouter(
  createRoutesFromElements(
    <Route
      element={<Team />}
      path="teams/:teamId"
      loader={async ({ params }) => {
        return fetch(`/fake/api/teams/${params.teamId}.json`);
      }}
      action={async ({ request }) => {
        return updateFakeTeam(await request.formData());
      }}
      errorElement={<ErrorBoundary />}
    />,
  ),
);
```

## 更多 API

若想要了解完整的路由 API 信息，可至 [react-router 官网](https://reactrouter.com/web/guides/start) 查看。
