gnosis23 / hello-world-blog

还是 issues 里面写文章方便
https://bohao.work
0 stars 0 forks source link

React Router #21

Open gnosis23 opened 5 years ago

gnosis23 commented 5 years ago

搭个开发框架熟悉下React,想配个路由可没那么轻松。

测试

你知道下面问题的答案吗?

初级阶段

最最最普通的路由配置,手工编码路由地址。

// index.js
ReactDOM.render(
  <BrowserRouter>
    <AppRouter />
  </BrowserRouter>,
  document.getElementById('root')
);

// router.js
const AppRouter = () => (
  <Switch>
      <Route path="/" exact component={Foo} />
      <Route path="/foo" component={Foo} />
      <Route path="/bar" component={Bar} />
  </Switch>
);

export default AppRouter;

动态加载代码

使用 react-loadable 包装返回类

export default Loadable({
  loader: () => import('./Foo'),
  loading: <div>loading...</div>
});
gnosis23 commented 2 years ago

React Router 6 新特性

嵌套路由

嵌套路由字面意思指的是把路由组件嵌套起来,形成层级。通过和相对路径结合,作用是把 url 中的每段(segment)和组件层级联系起来。

举个例子,下面这个路由 example.com/sales/invoices/20200:sales对应销售页面,invoices对应销售页面的发票部分,它们可以和组件层级结合起来,可以参考下这个图片demo

相应代码如下

<Routes>
  <Route path="/" element={<App />}>
    <Route path="expenses" element={<Expenses />} />
    <Route path="invoices" element={<Invoices />}>
      <Route
        index
        element={
          <main style={{ padding: "1rem" }}>
            <p>Select an invoice</p>
          </main>
        }
      />
      <Route path=":invoiceId" element={<Invoice />} />
    </Route>
</Routes>

能想到的好处有:

Data Loader

Route 里面现在可以带一个 loader 函数

<Route
  path="/"
  loader={async ({ request }) => {
    // loaders can be async functions
    const res = await fetch("/api/user.json", {
      signal: request.signal,
    });
    const user = await res.json();
    return user;
  }}
  element={<Root />}
/>

function Root() {
  const user = useLoaderData();
  // data from <Route path="/">
}

Navigation State

提供了页面切换状态

{navigation.state === "loading" && <GlobalSpinner />}

骨架屏与Suspense

官方提供了 Suspense 和 Await 方案:

import {
  Await,
  defer,
  useLoaderData,
} from "react-router-dom";
import { getPackageLocation } from "./api/packages";

async function loader({ params }) {
  const packageLocationPromise = getPackageLocation(
    params.packageId
  );

  return defer({
    packageLocation: packageLocationPromise,
  });
}

export default function PackageRoute() {
  const data = useLoaderData();

  return (
    <main>
      <h1>Let's locate your package</h1>
      <React.Suspense
        fallback={<p>Loading package location...</p>}
      >
        <Await
          resolve={data.packageLocation}
          errorElement={
            <p>Error loading package location!</p>
          }
        >
          {(packageLocation) => (
            <p>
              Your package is at {packageLocation.latitude}{" "}
              lat and {packageLocation.longitude} long.
            </p>
          )}
        </Await>
      </React.Suspense>
    </main>
  );
}

这不就是 use 要干的事情吗?

gnosis23 commented 1 year ago

React Router 6 新特性 续

react router 支持 form 了。不过原生组件那么简单,实际中要怎么用?