xiaochengzi6 / Blog

个人博客
GNU Lesser General Public License v2.1
0 stars 0 forks source link

route V6 总结 #75

Open xiaochengzi6 opened 1 year ago

xiaochengzi6 commented 1 year ago

react-router 6.11.1

React-router

react 有两种模式一种使用 数据路由 另外一种使用组件式路由

具体要配合 react-router 库去看

一、<Routers> 组件代替原有<Switch>,所有子路由都用基础的Router children来表示

<Routers location>
  <Route path="/top" element={<Top />}/>
  <Route path="/content" childes>
</Routers>

<Route> 可以用匹配路由渲染组件的

<Route 
 path="/top"
 loader={({params}) => { console.log(params)}}
 action={({params}) => {}}
 element={<Top />}>
  1. path: 要与 URL 匹配的路径模式,以确定此路由是否匹配 URL、 link href 或表单操作

  2. loader: 在路由呈现之前事前可以进行数据请求, 使用 useLoaderData hook 取到值

例如:

function Root () {
  const router = createBrowserRouter({
    path: '/',
    element: <Element />,
    loader: () => {
      // 这里进行数据请求
      return featchData() 
    }
  })
}

function Element() {
  // 取到 data 数据
  const data = useLoaderData() 

  // ...
}
  1. action:

  2. errorElement/errorBoundary: 当路由在渲染时抛出异常,在 loader 或 action 中,这个 React 元素/组件将会代替正常的 element / Component 进行渲染。

<Route
  path="/for-sale"
  element={<Properties />}
  // 如果发生错误
  // 这里会显示 ErrorBoundary 组件
  errorElement={<ErrorBoundary />}
/>
  1. layz :为了使你的应用程序包小并支持你的路由的代码分割,每个路由都可以提供一个异步函数,该函数解析你的路由定义中不匹配路由的部分 ( loader 、 action 、 Component / element 、 ErrorBoundary / errorElement 等)。

这里理解不太到位

let routes = createRoutesFromElements(
<Route path="/" element={<Layout />}>
<Route path="a" lazy={() => import("./a")} />
<Route path="b" lazy={() => import("./b")} />
</Route>
);

每个 lazy 函数通常会返回一个动态导入的结果。

参考:https://reactrouter.com/en/main/route/lazy

{
      path: "messages",
      async lazy() {
        let { messagesLoader, Messages } = await import(
          "./pages/Dashboard"
        );

        // 这里提供 loader 和 Component 数据
        return {
          loader: messagesLoader,
          Component: Messages,
        };
      },
    },
  1. handle 任何应用程序特定的数据,主要配合 useMatches 使用

使用 useMatches 钩子能够获取以下数据类型

{
  id,
  pathname,
  data,
  params,
  // 获取 handle 函数
  handle
}

二、使用 <Outlet> 来渲染它们的子路由元素。这样可以在渲染子路由时显示嵌套的 UI。如果父路由完全匹配,则会渲染子索引路由,如果没有索引路由,则不会渲染任何内容。

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      // 在这里使用
      <Outlet />
    </div>
  );
}

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

三、useNavigateNavigate

使用 useNavigate 可以返回一个函数,以函数的形式导航

// useNavigate 接收的参数
interface NavigateFunction {
  (
    to: To,
    options?: {
      replace?: boolean;
      state?: any;
      relative?: RelativeRoutingType;
    }
  ): void;
  (delta: number): void;
}
  1. 要么传递一个 To 值(与 相同的类型),带有可选的第二个 { replace, state } 参数,要么
  2. 传递您想要在历史堆栈中前进的增量。例如, navigate(-1) 等同于点击后退按钮。
function Top() {
  const navigate = useNavigate()

  useEffect(() => {
    navigate("/top")
  })

  return(
    <div>   </div>
  )
}

四、<Link> 让用户通过点击跳转到另一个页面

参考:https://baimingxuan.github.io/react-router6-doc/components/link.html#relative

import * as React from "react";
import { Link } from "react-router-dom";

function UsersIndexPage({ users }) {
  return (
    <div>
      <h1>Users</h1>
      <ul>
        {users.map((user) => (
          <li key={user.id}>
            // 跳转
            <Link to={user.id}>{user.name}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
}

五、<Await>用于呈现具有自动错误处理的延迟值(是一个延迟的值)

通常配合 React.Suspense 使用,它是在子组件未加载完时选它提供的组件,具体:https://zh-hans.react.dev/reference/react/Suspense#suspense

参考:https://baimingxuan.github.io/react-router6-doc/components/await.html#await


function Book() {
  const { book, reviews } = useLoaderData();
  return (
    <div>
      <h1>{book.title}</h1>
      <p>{book.description}</p>
      // 如果子组件未加载就先渲染 fallback 提供的组件
      <React.Suspense fallback={<ReviewsSkeleton />}>
      // 延迟的值
        <Await
          // 接受从延迟、加载器 值返回的 promise,以便解决和渲染。
          resolve={reviews}
          // 当Promise被拒绝时,错误元素将呈现而不是子元素
          errorElement={
            <div>Could not load reviews 😬</div>
          }
          // 可以是React元素或函数。
          //   是React函数,useAsyncValue ()将提供数据:
          children={(resolvedReviews) => (
            <Reviews items={resolvedReviews} />
          )}
        />
      </React.Suspense>
    </div>
  );
}

hook

  1. useActionData此钩子提供了上一次导航的 action 结果的返回值,如果没有提交,则为 undefined 。

  2. useAsyncError 从最近的 [await] 组件返回拒绝值。

function ErrorElement() {
  const error = useAsyncError();
  return (
    <p>Uh Oh, something went wrong! {error.message}</p>
  );
}

<Await
  resolve={promiseThatRejects}
  errorElement={<ErrorElement />}
/>;
  1. useAsyncValue 从最近的 祖先组件返回已解析的数据。
function Child() {
  // 这里拿到值
  const asyncValue = useAsyncValue()

}
<Await> 
  <Child />
</Await>
  1. useBeforeUnload是 window.onbeforeunload 的辅助工具 在用户离开页面之前,将重要的应用程序状态保存在页面上

  2. useLocation返回当前的location (opens new window)对象。如果您想在当前位置更改时执行一些副作用,这可能会很有用。

  3. useMatch 传入一个 url 与当前路由去匹配,如果匹配上就返回一个匹配的信息,否则返回null

场景题

  1. 重定向
<Route 
 path='/home'
 loader={async () => {
   const result = awit featch()
   if(!result) {
     redirect('/login')
   }
 }}
 >

Redirect 组件被移除,取而代之的是Navigate 组件

<Navigate>重定向 当 <Navigate replace to="/error-page"> 可以替换当前页面,也就是不会改变历史消息

// 条件性重定向
<Route 
 path="/login"
 element={login ? <Login /> : <Navigate to="/navigate" />}
 >
function Top (){
  const navigate = useNavigate()

  return (
    <div>
      //  重定向
       <button onClick={() => navigate('/data')}>
    </div>
  )
}

参考:https://juejin.cn/post/7114889463825694727