react-router6新特性数据路由器、hook详解

react PC端项目构建TS,react@18.2.0+antd+vite+axios+redux+sass+ts 完整版代码下载:
https://download.csdn.net/download/randy521520/88922625
react PC端项目构建,react@18.2.0+antd+vite+axios+redux+sass完整版代码下载:
https://download.csdn.net/download/randy521520/88922569
react移动端项目构建TS,react@18.2.0+react-vant+vite+axios+redux+sass+ts完整版代码下载:
https://download.csdn.net/download/randy521520/88917557
react移动端项目构建,react@18.2.0+react-vant+vite+axios+redux+sass完整版代码下载:
https://download.csdn.net/download/randy521520/88917543

一、react-router简介

react-router 是一个用于处理 React 应用程序中路由管理的库,它提供了一种简单而强大的方式来实现单页面应用程序(SPA)中的路由控制。通过 react-router,可以轻松地定义应用程序的不同路由,使用户能够在应用程序中浏览不同的页面或视图。数据路由器比普通的路由器支持加载器、操作、提取器等功能。

二、数据路由器

1.createBrowserRouter:创建BrowserRouter数据路由器

import * as React from "react";
import * as ReactDOM from "react-dom";
import {
  createBrowserRouter,
  RouterProvider,
} from "react-router-dom";

import Root, { rootLoader } from "./routes/root";
import Team, { teamLoader } from "./routes/team";

const router = createBrowserRouter([
  {
    path: "/",
    element: <Root />,
    loader: rootLoader,
    children: [
      {
        path: "team",
        element: <Team />,
        loader: teamLoader,
      },
    ],
  },
]);

ReactDOM.createRoot(document.getElementById("root")).render(
  <RouterProvider router={router} />
);

2.createHashRouter:创建createHashRouter数据路由器

import * as React from "react";
import * as ReactDOM from "react-dom";
import {
  createHashRouter,
  RouterProvider,
} from "react-router-dom";

import Root, { rootLoader } from "./routes/root";
import Team, { teamLoader } from "./routes/team";

const router = createHashRouter([
  {
    path: "/",
    element: <Root />,
    loader: rootLoader,
    children: [
      {
        path: "team",
        element: <Team />,
        loader: teamLoader,
      },
    ],
  },
]);

ReactDOM.createRoot(document.getElementById("root")).render(
  <RouterProvider router={router} />
);

3.createMemoryRouter:创建ceateMemoryRouter数据路由器

import {
  RouterProvider,
  createMemoryRouter,
} from "react-router-dom";
import * as React from "react";
import {
  render,
  waitFor,
  screen,
} from "@testing-library/react";
import "@testing-library/jest-dom";
import CalendarEvent from "./routes/event";

test("event route", async () => {
  const FAKE_EVENT = { name: "test event" };
  const routes = [
    {
      path: "/events/:id",
      element: <CalendarEvent />,
      loader: () => FAKE_EVENT,
    },
  ];

  const router = createMemoryRouter(routes, {
    initialEntries: ["/", "/events/123"],
    initialIndex: 1,
  });

  render(<RouterProvider router={router} />);

  await waitFor(() => screen.getByRole("heading"));
  expect(screen.getByRole("heading")).toHaveTextContent(
    FAKE_EVENT.name
  );
});

4.createStaticHandler:创建createStaticHandler数据路由器

import {
  createStaticHandler,
  createStaticRouter,
  StaticRouterProvider,
} from "react-router-dom/server";
import Root, {
  loader as rootLoader,
  ErrorBoundary as RootBoundary,
} from "./root";

const routes = [
  {
    path: "/",
    loader: rootLoader,
    Component: Root,
    ErrorBoundary: RootBoundary,
  },
];

export async function renderHtml(req) {
  let { query, dataRoutes } = createStaticHandler(routes);
  let fetchRequest = createFetchRequest(req);
  let context = await query(fetchRequest);

  if (context instanceof Response) {
    throw context;
  }

  let router = createStaticRouter(dataRoutes, context);
  return ReactDOMServer.renderToString(
    <React.StrictMode>
      <StaticRouterProvider
        router={router}
        context={context}
      />
    </React.StrictMode>
  );
}

5.createStaticRouter:创建createStaticRouter数据路由器

import {
  createStaticHandler,
  createStaticRouter,
  StaticRouterProvider,
} from "react-router-dom/server";
import Root, {
  loader as rootLoader,
  ErrorBoundary as RootBoundary,
} from "./root";

const routes = [
  {
    path: "/",
    loader: rootLoader,
    Component: Root,
    ErrorBoundary: RootBoundary,
  },
];

export async function renderHtml(req) {
  let { query, dataRoutes } = createStaticHandler(routes);
  let fetchRequest = createFetchRequest(req);
  let context = await query(fetchRequest);
  if (context instanceof Response) {
    throw context;
  }

  let router = createStaticRouter(dataRoutes, context);
  return ReactDOMServer.renderToString(
    <React.StrictMode>
      <StaticRouterProvider
        router={router}
        context={context}
      />
    </React.StrictMode>
  );
}

6.RouterProvider:数据路由器组件

  • router:创建的路由器
  • fallbackElement:路由加载时显示的备用元素,如果路由加载过程中出现延迟或错误,可以显示此备用元素
  • future:预加载和延迟加载的配置信息。
    7.StaticRouterProvider:静态数据路由器组件,使用createStaticRouter创建的路由器
  • context: 静态路由上下文对象,用于在服务器端渲染时传递路由信息。
  • router:创建的路由器
  • hydrate: 用于将服务器端生成的内容与客户端的事件处理逻辑连接起来。
  • nonce: 用于安全策略的一次性随机数
    8.创建数据路由器相关参数
  • id:路由的唯一标识符,id: ‘id’
  • path:路由的路径,path: ‘/’
  • element:React 元素,用于渲染路由内容,element: <></>
  • children:子路由,children: [{}]
  • index:指示这是一个索引路由,索引路由是指当用户访问应用程序的根路径时所匹配的路由,常用于子路由,index: false
  • caseSensitive:指示路由是否区分大小写,react-router V6版本无效果,caseSensitive: false
  • lazy:用于定义懒加载路由的函数, lazy:()=>import(componentPath)
  • loader:用于懒加载路由的加载器,loader: async ({params,request,context}) => {}
  • action:路由提交事件,action: async ({params,request,context}) => {}
  • errorElement: <></>:错误时显示的元素。
  • Component: ‘’:React 组件类型。
  • hasErrorBoundary: false:指示路由是否有错误边界。
  • shouldRevalidate: false:指示是否应该重新验证路由。
  • ErrorBoundary: <></>:错误边界组件。
  • handle: ‘’:路由的处理函数。
  • hydrateFallbackElement: <></>:用于服务端渲染时的回退元素。
  • HydrateFallback: <></>:用于服务端渲染时的回退组件。
三、数据路由器之useMatches:返回页面上的当前路由匹配项
import {useMatches} from "react-router-dom";

const List = () => {
    console.log(useMatches())
    return (<>列表页</>);
};

export default List;
四、数据路由器之useNavigation:获取导航的所有信息
import {useNavigation} from "react-router-dom";

const List = () => {
    console.log(useNavigation())
    return (<>列表页</>);
};

export default List;
五、数据路由器之useLoaderData:处理加载数据,路由器需配置loader

1.路由器配置

import {createBrowserRouter, Navigate} from "react-router-dom";
import Home from "@pages/home/home.jsx";
import List from "@pages/list/list.jsx";

const routes = createBrowserRouter([{
    path: '/',
    element: <Navigate to="/home" replace/>,
}, {
    path: '/home',
    element: <Home/>,
}, {
    path: '/list/:id',
    element: <List/>,
    loader: async ({params,request,context}) => {
        console.log(params,request,context)
        return {useId:'ACTION'}
    }
}]);

export default routes;

2.跳转有加载器的路由页面

import {useNavigate} from "react-router-dom";

const Home = () => {
    const navigate = useNavigate();
    const goRouter = () => {
        navigate('/list/1')
    }
    return (<>
        <button onClick={goRouter}>跳转list</button>
    </>);
};

export default Home;

3.加载器路由页面

import {useLoaderData} from "react-router-dom";

const List = () => {
    console.log(useLoaderData())
    return (<>列表页</>);
};

export default List;
六、数据路由器之useSubmit、<Form>组件:处理提交的Hook,useSubmit(formData,option)

1.option配置

  • method: 用于提交方法。默认为 “GET”。
  • action: 用于提交路径。默认为当前路由的路径,会跳转到该路由
  • encType: 用于提交编码类型。默认为 “application/x-www-form-urlencoded”。
  • fetcherKey: 当 navigate=false 时使用的特定 fetcherKey。
  • navigate: 当设置为 false 时,将使用 fetcher 而不是导航。
  • replace: 设置为 true 时,将替换浏览器历史堆栈中的当前条目。默认为 false。
  • state: 添加到此导航的历史堆栈条目的状态对象。
  • relative: 确定表单操作相对于路由层次结构还是路径名。如果要选择退出路由层次结构而是基于 / 分隔的 URL 段路由,则使用此选项。
  • preventScrollReset: 在基于浏览器的环境中,使用 组件时,防止在此导航后重置滚动。
  • unstable_flushSync: 为此导航的状态更新启用 flushSync。
  • unstable_viewTransition: 在此提交导航上启用视图过渡。
    1.路由器配置
import {createBrowserRouter, Navigate} from "react-router-dom";
import Home from "@pages/home/home.jsx";
import List from "@pages/list/list.jsx";

const routes = createBrowserRouter([{
    path: '/',
    element: <Navigate to="/home" replace/>,
}, {
    path: '/home',
    element: <Home/>,
}, {
    path: '/list/:id',
    element: <List/>,
    action: async ({params,request,context}) => {
        console.log(params,request,context)
        let formData = await request.formData();
        return {useId:params.id,name:formData.get('name')}
    },
}]);

export default routes;

2.跳转有action的路由页面

import {useSubmit} from "react-router-dom";

const Home = () => {
    const submit = useSubmit();
    const goRouter = () => {
        submit({name:'张三'}, { method: "post", action: "/list/1" });
    }
    return (<>
        <button onClick={goRouter}>跳转list</button>
    </>);
};

export default Home;

3.获取actipn数据:useActionData

import {useActionData} from "react-router-dom";


const List = () => {
    const data = useActionData();
    console.log(data)
    return (<>列表页</>);
};

export default List;

4.除了使用useSubmit跳转,还可以使用组件

  • method:表单数据提交的方式,可以是 “get”、“post”、“put”、“patch” 或 “delete”.
  • encType:表单数据的编码类型,可以是 “application/x-www-form-urlencoded”、“multipart/form-data” 或 “text/plain”.
  • action:表单提交的目标 URL.
  • onSubmit:处理表单提交事件的回调函数.
  • fetcherKey:指定表单提交时使用的fetcher key.
  • navigate:指定是否在提交表单后进行页面导航.
  • preventScrollReset:指定是否阻止表单提交后的滚动位置重置.
  • relative:导航相对位置的方式,可以是 “route” 或 “path”.
  • reloadDocument:指定是否在提交表单后重新加载文档.
  • replace:指定是否使用替换导航.
  • state:要传递的状态数据.
  • unstable_viewTransition:指定是否使用不稳定的视图过渡.
import {Form} from "react-router-dom";

const Home = () => {
    return (<>
        <Form method="post" action="/list/1">
            <button type="submit">跳转list</button>
        </Form>
    </>);
};

export default Home;
七、数据路由器之useRouteLoaderData:子路由获取父路由的加载数据

1.路由器配置

import {createBrowserRouter, Navigate} from "react-router-dom";
import Home from "@pages/home/home.jsx";
import List from "@pages/list/list.jsx";

const routes = createBrowserRouter([{
    path: '/',
    element: <Navigate to="/home" replace/>,
}, {
    id:'home',
    path: '/home',
    element: <Home/>,
    loader: ()=>{
        return {name:'home'}
    },
    children:[{
        path: 'list',
        element: <List/>,
    }]
}]);

export default routes;

2.父路由页面

import {Outlet} from "react-router-dom";

const Home = () => {
    return (<>
        <div>home页</div>
        <Outlet/>
    </>);
};

export default Home;

3.子路由页面

import { useRouteLoaderData} from "react-router-dom";

const List = () => {
    const parentLoaderData = useRouteLoaderData('home');
    console.log(parentLoaderData)
    return (<>列表页</>);
};

export default List;
八、数据路由器之useBlocker:用于处理阻塞操作的 Hook,页面离开前处理一些操作,如:是否确认离开该页面
import {useBlocker, useNavigate} from "react-router-dom";

const Home = () => {
    const navigate = useNavigate();
    let blocker = useBlocker(({ currentLocation, nextLocation }) => currentLocation.pathname !== nextLocation.pathname);
    const goRouter = () => {
        navigate('/list/1')
    }
    return (<>
        <button onClick={goRouter}>跳转列表</button>

        {blocker.state === "blocked" ? (
            <div>
                <p>是否离开hone页</p>
                <button onClick={() => blocker.proceed()}>确定</button>
                <button onClick={() => blocker.reset()}>取消</button>
            </div>
        ) : null}
    </>);
};

export default Home;
九、数据路由器之useFormAction:自动解析 submit 的操作
import {useFormAction,useSubmit} from "react-router-dom";

const Home = () => {
    let submit = useSubmit();
    let action = useFormAction();
    const goRouter = () => {
        submit({}, { action });
    }
    return (<>
        <button onClick={goRouter}>跳转列表</button>
    </>);
};

export default Home;
十、数据路由器之unstable_usePrompt:离开页面之前给出弹框提示
import {unstable_usePrompt, useNavigate} from "react-router-dom";

const Home = () => {
    let navigate = useNavigate()
    const goRouter = () => {
        navigate('/list/1')
    }
    unstable_usePrompt({
        message: "是否离开页面?",
        when: ({ currentLocation, nextLocation }) => currentLocation.pathname !== nextLocation.pathname,
    });
    return (<>
        <button onClick={goRouter}>跳转列表</button>
    </>);
};

export default Home;
十一、数据路由器之useFetcher:不更改 URL 的情况下调用其他导航的loader、action

1.fetcher.submit(formData,option):提交数据,路由需配置action
2.fetcher.load(href):加载对应href加载器,路由需配置loader
3.fetcher.state:提取器状态

  • idle:空闲状态
  • submitting:使用 POST、PUT、PATCH 或 DELETE 进行提取程序提交,正在调用路由操作
  • loading:提取器正在调用加载程序
    4.fetcher.data:从加载程序或操作返回的数据存储在此处。一旦设置了数据,即使通过重新加载和重新提交,它也会保留在提取器上。
    5.fetcher.formData:使用 <fetcher.Form> 或 fetcher.submit() 时的表单数据I。
    6.fetcher.json:使用 fetcher.submit(data, { formEncType: “application/json” }) 时,提交的 JSON 可通过 fetcher.json 获得。
    7.fetcher.text:使用 fetcher.submit(data, { formEncType: “text/plain” }) 时,提交的文本可通过 fetcher.text 获得。
    8.fetcher.formAction:获取提交的url
    9.fetcher.formMethod:获取提交的方法
    10.使用案例
  • 路由器配置
import {createBrowserRouter, Navigate} from "react-router-dom";
import Home from "@pages/home/home.jsx";
import List from "@pages/list/list.jsx";

const routes = createBrowserRouter([{
    path: '/',
    element: <Navigate to="/home" replace/>,
}, {
    path: '/home',
    element: <Home/>,
}, {
    path: '/list/:id',
    element: <List/>,
    loader: async ({params,request,context}) => {
        return {useId:params.id,name:'loader'}
    },
    action: async ({params,request,context}) => {
        console.log(params,request,context)
        let formData = await request.formData();
        return {useId:params.id,name:formData.get('name')}
    },
}]);

export default routes;
  • 跨页面调用list路由的action、loader,页面提交或加载之后会保存在提取器中,可以根据key在其他页面获取
import {useFetcher, useNavigate} from "react-router-dom";
import {useEffect} from "react";

const Home = () => {
    const fetcher = useFetcher({key:'home'});
    const navigate = useNavigate();
    useEffect(() => {
        if (fetcher.state === "idle" && !fetcher.data) {
            fetcher.load("/list/1");
        }
    }, [fetcher]);

    const goRouter = ()=>{
        navigate('/list/1');
    }

    const onSubmit = ()=>{
        fetcher.submit({name:'useFetcher'}, {method:'post',action:'/list/1'});
    }

    return (<>
            <button onClick={onSubmit}>提交数据</button>
            <button onClick={goRouter}>跳转list</button>
            <div>{JSON.stringify(fetcher.data)}</div>
        </>
    );
};

export default Home;
  • 在list页面获取提取器中的内容
import {useFetcher} from "react-router-dom";


const List = () => {
    const fetcher = useFetcher({key:'home'});
    return (<>{JSON.stringify(fetcher.data)}</>);
};

export default List;
十二、数据路由器之useFetchers:用于没配置action、loader的路由,获取已配置路由的fetcher

1.路由器配置

import {createBrowserRouter, Navigate} from "react-router-dom";
import Home from "@pages/home/home.jsx";
import List from "@pages/list/list.jsx";
import Detail from "@pages/detail/detail.jsx";

const routes = createBrowserRouter([{
    path: '/',
    element: <Navigate to="/home" replace/>,
}, {
    path: '/home',
    element: <Home/>,
}, {
    path: '/list/:id',
    element: <List/>,
    loader: async ({params,request,context}) => {
        return {useId:params.id,name:'loader'}
    },
    action: async ({params,request,context}) => {
        console.log(params,request,context)
        let formData = await request.formData();
        return {useId:params.id,name:formData.get('name')}
    },
},{
    path:'detail',
    element: <Detail/>
}]);

export default routes;

2.跨页面调用list路由的action、loader

import {useFetcher, useNavigate} from "react-router-dom";
import {useEffect} from "react";

const Home = () => {
    const fetcher = useFetcher({key:'home'});
    const navigate = useNavigate();
    useEffect(() => {
        if (fetcher.state === "idle" && !fetcher.data) {
            fetcher.load("/list/1");
        }
    }, [fetcher]);

    const goRouter = ()=>{
        navigate('/detail');
    }

    const onSubmit = ()=>{
        fetcher.submit({name:'useFetcher'}, {method:'post',action:'/list/1'});
    }

    return (<>
            <button onClick={onSubmit}>提交数据</button>
            <button onClick={goRouter}>跳转detail</button>
            <div>{JSON.stringify(fetcher.data)}</div>
        </>
    );
};

export default Home;

3.在detail页面获取提取器中的内容,页面刷新之后是获取不到的

import {useFetchers} from "react-router-dom";
import {useEffect, useState} from "react";

const Detail = () => {
    const fetchers = useFetchers({key: 'home'});
    let [homeFetch,setHomeFetch] = useState({});
    useEffect(() => {
        setHomeFetch(fetchers[0]);
    }, []);

    return (<>
        {JSON.stringify(homeFetch?.data)}
    </>);
};

export default Detail;
十三、其他

1.useRevalidator:用于重新验证的 Hook。
2.useRouteError:处理路由错误的 Hook
3.<ScrollRestoration/>:加载程序完成后,此组件将模拟浏览器在位置更改时的滚动恢复,以确保滚动位置恢复到正确的位置

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值