router

补充信息

基于 react-router 的路由解决方案。

hooks

useNavigate

declare function useNavigate(): NavigateFunction;

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

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

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

declare function useLocation(): Location;

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

useLocation 返回当前 url 对应的 location 对象。每当路由更新的时候,都会拿到一个新的 location 对象。

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

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

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

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

export declare function useRouteError(): unknown;

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

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;

组件

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 组件进行路由跳转。

<Link to="/about">About</Link>
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

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

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

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

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 的函数的参数:

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 的函数的参数:

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 官网 查看。