React Router React Router v7 示例
工作模式
Declareative 声明式, 使用路由组件匹配 url, 导航路由
Data 在 React rendering 外配置路由, 支持 data APIs
Framework 包含 Data mode 模式的全栈框架
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 createRoot (root).render ( <BrowserRouter > <Routes > <Route path ="/" element ={ <Root /> } /> </Routes > </BrowserRouter > ); const router = createBrowserRouter ([ {path : '/' , Component : Root , loader : rootLoader} ]); createRoot (root).render (<RouterProvider router ={router}/ > );export default [ index ('./home.tsx' ), route ('about' , './about.tsx' ), route ('dashboard' , './dashboard.tsx' , [ index ('./home.tsx' ), route ('settings' , './setting.tsx' ) ]), layout ('./auth/layout.tsx' , [ route ('login' , './auth/login.tsx' ), route ('register' , './auth/register.tsx' ) ]), ...prefix ("projects" , [ index ("./projects/home.tsx" ), layout ("./projects/project-layout.tsx" , [ route (":pid" , "./projects/project.tsx" ), route (":pid/edit" , "./projects/edit-project.tsx" ), ]), ]) ]
自动将 loaderData, actionData, params, matches 作为 props 传递给组件
1 2 3 4 5 6 7 8 9 10 11 12 export async function loader ( ){} export async function clientLoader ({params} ){} export async function action ( ){}export async function clientAction ( ){}export function ErrorBoundary ( ){} export function headers ( ){} export function links ( ){} export function meta ( ){} export const handle = {} export function shouldRevalidate ( ){}
以下部分为 React Router v6
路由器 创建路由方式
使用 createBrowserRouter 和 RouterProvider
对象形式
JSX 元素(createRoutesFromElements)
使用 Routes, Route, BrowserRouter|HashRouter 内置组件
使用 useRoutes hook 和 BrowserRouter|HashRouter 内置组件
不支持 data APIs
<BrowserRouter>
<MemoryRouter>
<HashRouter>
<NativeRouter> 用于 React Native
<StaticRouter>
支持 data APIs 使用此方式创建路由, 同时启用用于数据获取的 loader, actions, fetchers 等 API
createBrowserRouter
createMemoryRouter
createHashRouter
createStaticRouter
createBrowserRouter
basename 基础路径
future 用于启用新版本语法的配置对象
hydrationData 当使用服务器端渲染时允许从服务器端获取数据
unstable_dataStrategy 低水平 API, 将会覆盖 React Router 内部的 loader, action 的执行
unstable_patchRoutesOnMis
window 用于区分环境, 对开发者工具或者测试来说非常有用
返回值
1 2 3 4 5 6 7 8 9 const routes = [];const router = createBrowserRouter (routes, { basename : '/app' , hydrationData : { root : { } }, });
RouterProvider 路由根组件, 所有的路由对象或者 Data APIS 都通过此组件注入 React 应用程序
router 路由信息
fallbackElement 后备内容
future 用于启用新版本语法的配置对象
1 2 3 4 5 6 7 8 9 10 11 12 import {StrictMode } from 'react' ;import {createRoot} from 'react-dom/client' ;import {createBrowserRouer, createRoutesFromElements, RouterProvider , Route } from 'react-router-dom' ;const root = createRoot (document .getElementById ('root' ))root.render ( <StrictMode > <RouterProvider router ={router} fallbackElement ={ <SpinnerOfDom /> }/> </StrictMode > );
1 2 3 4 5 6 7 8 9 10 11 12 13 const router = createBrowserRouter ([ { path : '/' , element : <Root /> , loader : rootLoader, action : rootAction, errorElement : <ErrorPage /> , children : [ {index : true , element : <Dashboard /> } ] } ])
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const router = createBrowserRouter ( createRoutesFromElements ( <Route path ="/" element ={ <Root /> } errorElement={<ErrorPage /> } loader={rootLoader} action={rootAction} > <Route index element ={ <Dashboard /> }/> {/* ... */} </Route > ) );
createStaticHandler 通常用于服务器端渲染的 数据获取和提交, 配合 createStaticRouter
使用
routes 路由信息
opts
basename
future 用于启用新版本语法的配置对象
mapRouteProperties
返回值
staticHandler.dataRoutes 路由信息
staticHandler.query() 执行当前请求的 action, loader 并返回 context 包含了渲染页面的所有数据
request 请求
opts
routeId 如果需要调用不同的路由的 action 或 loader, 传入指定的 routeId
requestContext 将请求上下文信息传入 action 或 loader
staticHandler.query() 返回值
createStaticRouter
routes 路由信息
context 请求的上下文信息
opts
返回值
StaticRouterProvider 接收来自 createStaticHandler
的 context 和 createStaticRouter
的 router, 用于服务器端渲染
router 通过 createStaticRouter 创建的路由
context 接收来自 staticHandler.query() 返回的结果作为数据
hydrate 是否禁用客户端自动数据连接
nonce 标识使用严格 CSP(安全内容策略) 时允许资源的加密随机数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 "server.jsx" import {StrictMode } from 'react' ;import {createStaticHandler, createStaticRouter, StaticRouterProvider } from 'react-router-dom/server' ;import {renderToString} from 'react-dom/server' ;let handler = createStaticHandler (routes);app.get ('*' , async (req, res) => { let fetchRequest = createRequest (req, res); let context = await handler.query (fetchRequest); let router = createStaticRouter (handler.dataRoutes , context); let html = renderToString ( <StrictMode > <StaticRouterProvider router ={router} context ={context} /> </StrictMode > ); res.send ("<!DOCTYPE html>" + html); }); const listener = app.listen (3000 , () => { let {port} = listener.address (); console .log (`listening on port ${port} ` ); }); "client.jsx" import {StrictMode } from 'react' ;import {createBrowserRouter, RouterProvider } from 'react-router-dom' ;import {hydrateRoot} from 'react-dom/client' ;let router = createBrowserRouter (routes);const root = hydrateRoot ( document .getElementById ('root' ), <StrictMode > <RouterProvider router ={router}/ > </StrictMode > );
Route React Router 创建路由的 内置组件 , data APIs 由类似 createBrowserRouter 创建的路由才有效
index 标识当路由未匹配到时默认匹配
path 路由
caseSensitive path 是否区分大小写
handle 当前路由的任意数据, 作用同 useMatches
element/component 当路由匹配时渲染, 使用 element 意味着不需要再额外的使用 passProps 风格的方式传递 props
1 2 3 4 5 6 7 8 9 10 11 <Route path=":userId" component={Profile } passProps={{animate : true }} /> <Route path =":userId" render ={(routeProps) => (<Profile routeProps ={routeProps} animate ={true} /> )} /><Route path =":userId" children ={({match}) => ( match ? <Profile match ={match} animate ={true} /> : <NotFound /> )} /> <Route path =":userId" element ={ <Profile animate ={true} /> } />
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import {createBrowserRouter} from 'react-router-dom' ;const router = createBrowserRouter ([ { path : '/' , element : <Root /> , errorElement : <ErrorPage /> , loader : async ({request, params}) => { return fetch (); }, action : async ({request}) => { return update (await request.formData ()); }, children : [] } ]);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import {createBrowserRouter, createRoutesFromElements, Route } from 'react-router-dom' ;const router = createBrowserRouter (createRoutesFromElements ( <Route path ="/" element ={ <Root /> } errorElement={<ErrorPage /> } lazy={() => import('./a')} loader={async ({request, params}) => { return fetch(); }} action={async ({request}) => { return update(await request.formData()); }} > <Route index path ="" element ={ <DashBoard /> }/> </Route > ))
Route.action 当 React Router 抽象了异步 UI 和重新验证的复杂性时, 为应用程序提供了一种使用简单的 HTML 和 HTTP 语句执行数据更改的方法
每当应用程序向路由发送 non-get(POST, PUT, PATCH, DELETE) 提交时, 都将调用此 action
动态路由参数分别传递给 loader , useMatch , useParams
request request 请求实例
params 动态路由参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import {createBrowserRouter, createRoutesFromElements, Route } from 'react-router-dom' ;const router = createBrowserRouter ( createRoutesFromElements ( <Route path ="/projects/:id/edit" action ={async ({request , params }) => { console.log(params.id); const formData = request.formData(); return editProjectById(params.id); }} > {/* .... */} </Route > ) );
以下几种方式都将调用 Route 的 action
1 2 3 4 5 6 7 8 9 10 import {useFetcher, useSubmit} from 'react-router-dom' ;const fetcher = useFetcher ();const submit = useSubmit ();<Form method ="post" action ="/projects" /> ;<fetcher.Form method ="put" action ="/projects/123/edit" /> ;submit (data, {method : 'post' , action : '/projects' });fetcher.submit (data, {method : 'put' , action : '/projects/123/edit' })
Route.loader 组件渲染之前调用定义的 loader 函数并将返回的数据传入 React 元素
动态路由参数分别传递给 action , useMatch , useParams
params 动态路由参数
request request 请求实例
hydrate 服务器端渲染时处理 hydrate 数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import {createBrowserRouter, createRoutesFromElements, Route , useLoaderData} from 'react-router-dom' ;const router = createBrowserRouter ( createRoutesFromElements ( <Route path ="/projects/:id" element ={ <Projects /> } loader={async ({request, params}) => { console.log(params.id); const res = await fetch(); if(res.status == 404) { throw new Response('Not Found', {status: 404}); } return res.json(); }} > {/* ... */} </Route > ) ) function Projects ( ){ const projects = useLoaderData (); return ( projects ) }
Route.lazy 路由懒加载
1 2 3 4 5 6 7 8 9 10 11 12 import {createBrowserRouter, createRoutesFromElements, Route } from 'react-router-dom' ;const router = createBrowserRouter ( createRoutesFromElements ( <Route path ="/" element ={ <Layout /> } > <Route path ="a" lazy ={() => import('./a')} /> <Route path ="b" lazy ={() => import('./b')} /> </Route > ) )
Route.shouldRevalidate 如果定义了此函数, 将在路由的 loader 调用之前执行此函数验证新数据, 如果返回 false 则不在调用 loader 并且保持当前页面数据不变
Route.errorElement/errorBoundary 当组件的 loader, action 或者在渲染过程中抛出错误时代替 element 显示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import {createBrowserRouter, createRoutesFromElements, Route } from 'react-router-dom' ;const router = createBrowserRouter ( createRoutesFromElements ( <Route errorElement ={ <ErrorElement /> } loader={async ({request, params}) => { const res = await fetch(); if(res.status == 404){ throw new Response('Not Found', {status: 404}); } const json = res.json(); return {json} }} > {/* ... */} </Route > ) )
Route.hydrateFallbackElement/hydrateFallback 初始化服务器端渲染的内容没有被 hyrate 的组件, 如果未使用类似 createBrowserRouter 创建的路由则无效, 通常 SSR 的应用不会使用此项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import {createBrowserRouter} from 'react-router-dom' ;const router = createBrowserRouter ([ { id : 'root' , path : '/' , loader : rootLoader, Component : Root , children :[ { id : 'invoice' , path : 'invoice/:id' , loader : invoiceLoader, Component : Invoice , hydrateFallback : InvoiceFallback } ] } ], { future :{ v7_partialHydration : true , }, hydrationData :{ root :{ } } })
React Router 内置组件 Await 用于呈现具有自动错误处理功能的延迟值
children React 元素或者一个函数
resolve 返回一个 Promise 当延迟值被 resolve 后渲染
errorElement 当 resolve 被 reject 后渲染
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import {Await , useLoaderData, defer, Route } from 'react-router-dom' ;<Route loader ={async () => { let book = await getBook(); let reviews = getviews(); return defer({book, reviews}); }} element={<Book /> } > {/* ... */} </Route > function Book ( ){ const {book, reviews} = useLoaderData (); return ( <div > <h1 > title</h1 > <Await resolve ={reviews} > <Review /> </Await > </div > ) }
围绕普通 HTML 表单的包装器, 模拟浏览器进行客户端路由和数据更改
action
method
navigate 标识表单默认提交行为提交之后的动作是否跳转
fetchKey
replace 标识表单提交行为替换当前历史记录栈
relative 标识表单提交的后的跳转路径
reloadDocument 标识跳过 React Router 的表单提交行为并使用浏览器内置的表单默认行为
state
preventScrollReset 标识表单提交行为是否滚动页面位置
Link 路由导航
to
relative 相对路径, 默认为 Route 的相对层级
preventScrollRest 标识是否滚动到页面顶部
replace 标识是否替换当前历史记录栈
state 任何状态
reloadDocument
NavLink 特殊的 Link, 可以标识当前活动状态的导航
className 通过函数自定义样式
style 通过函数自定义样式
children
end 改变路由匹配逻辑, 当前路由是否以 to 结尾
caseSensitive 是否区分大小写
aria-current
reloadDocument
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import {NavLink } from 'react-router-dom' ;<NavLink to ="/message" className ={({isActive, isPending , isTransitioning }) => { return isPending ? 'pending' : isActive ? 'active' : '' }} style={({isActive, isPending, isTransitioning}) => { return { fontWeight: isActive ? 'bold' : '', color: isPending ? 'red' : 'black', viewTransitionName: isTransitioning ? 'slide' : '' } }} />
Navigate 当组件渲染后改变当前的路由, 通常用在 class 组件中, 建议使用 useNavigate Hook
to 跳转的目标路由
replace 是否使用替换模式
state 任何状态
relative
Outlet 渲染嵌套子路由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function DashBoard ( ){ return ( <div > <h1 > DashBoard</h1 > {/* ... */} <Outlet /> </div > ) } function App ( ){ return ( <Routes > <Route path ="/" element ={ <DashBoard /> }> <Route path ="message" element ={ <DashBoardMessage /> } /> <Route path ="tasks" element ={ <DashBoardTasks /> }/> </Route > </Routes > ) }
React Router 内置组件
Routes 匹配组件内的 Route, 用于不使用 createBrowserRouter 创建 Route 的情况
也可以使用 useRoutes Hook 创建路由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import {Routes , Route , BrowserRouter } from 'react-router-dom' ;function App ( ){ return ( <> <header > header</header > <BrowserRouter > <Routes > <Route path ="/" element ={ <DashBoard /> }> <Route path ="message" element ={ <DashBoardMessage /> } /> <Route path ="tasks" element ={ <DashBoardTasks /> } /> </Route > <Route path ="team" element ={ <Team /> } /> </Routes > </BrowserRouter > <footer > footer</footer > </> ) }
在渲染完成之后模拟浏览器在位置更改时的滚动恢复, 以确保滚动位置恢复到正确的位置
Links
React Router v7 支持
渲染所有的 link 标签
React Router v7 支持
渲染所有的 meta 标签
PrefetchPageLinks
React Router v7 支持
为即将导航的另一个页面的资源添加预取标签 <link rel=’prefetch|preload|modulepreload’ >
1 2 3 import { PrefetchPageLinks } from 'react-router' ;<PrefetchPageLinks page ='/absolute/path' /> ;
React Router 内置 Hook useActionData 获取上一个导航操作结果的返回值, 如果没有提交操作则返回 undefined
通常用于表单验证错误, 如果表单不正确可以返回错误并让用户重试
useAsyncError 获取最近的 Await 组件被 rejection 的结果
useAsyncValue 获取最近的 Await 组件被 resolved 的结果
useBeforeUnload 当用户离开页面时 (window.onbeforeunload) 保存重要的数据
useBlocker 阻止用户离开当前页面, 并呈现自定义 UI 提示用户允许确认导航
state 当前 blocker 的状态
unblocked 空闲没有阻止状态
blocked 阻止状态
proceeding 正在从阻断器中前进
proceed() 允许跳转
reset() 重置 blocker 状态并留在当前位置
1 const blocker = useBlocker ();
useFetcher 不想在更改 URL 的情况下调用 loader , action 获取页面的数据并重新验证, 或者需要同时进行多个更新
与服务器的许多交互不是导航事件, useFetcher 允许将 UI 插入到操作或 loader 中而不引起导航
key 默认为 内置组件 生成唯一的 key
fetcher.Form 像 Form 内置组件 一样, 只是不会引起导航
fetcher.state 标识当前 Fetcher 的状态
idle 空闲
submiting 由 fetcher 使用 post, put, patch, delete 提交正在调用路由操作
loading fetcher 正在调用 fetcher.load 或者在单独提交或调用用 useRevalidator
之后重新验证
fetcher.data 获取从 loader 或 action 加载的数据
fetcher.formData 当使用 fetcher.Form 和 fetcher.submit()
时, formData 可用
fetcher.json 当使用 fetcher.submit(data, {formEnctype: 'application/json'})
提交时可用
fetcher.text 当使用 fetcher.submit(data, {formEnctype: 'text/plain'})
提交时可用
fetcher.formAction 提交时的 form 的 url
fetcher.formMethod 提交时的方法 get, post, put, patch, delete
fetcher.load(href, options) 从 loader 中获取数据
fetcher.submit(data, options?) 包含了 useSubmit 调用的实例, 接收和 useSubmit 相同的参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import {useEffect} from 'react' ;import {useFetcher} from 'react-router-dom' ;function SomeCompoent ( ){ const fetcher = useFetcher ({key : 'new-key' }); useEffect (() => { fetcher.submit (data, options); fetcher.load (href); },[fetcher]); return ( <fetcher.Form action="/fetcher-action" method='post' > <button type ="submit" onclick ={(e) => { if(fetcher.state === 'idle' && !fetcher.data){ fetcher.submit(fetcher.formData?.get('username'), {formEnctype: 'application/json'}); } }}>Submit</button > <p > fetcher.formAction {fetcher.formAction}</p > <p > fetcher.formMethod {fetcher.formMethod}</p > {fetcher.json ? (<p > {fetcher.json}</p > ) : (<p > json: null</p > )} {fetcher.data ? (<div > {fetcher.data}</div > ) : (<div > loading data...</div > )} </fetcher.Form > ) }
useFetchers 获取除了 load, submit, Form 属性的 fetcher 数组
用在 Form 内置组件 内部自动解析当前路由的默认和相关操作
可以直接计算当前的 formAction
也可以用在 useSubmit 或者 fetcher.submit
中
1 2 3 4 5 6 7 8 9 10 11 12 13 import {useFormAction} from 'react-router-dom' ;function DeleteButton ( ){ const formAction = useFormAction ('destroy' ); return ( <button formAction ={formAction} formMethod ="post" > Delete </button > ) }
1 2 3 const submit = useSubmit ();const formAction = useFormAction ('delete' );submit (formData, {formAction});
useHref useInRouterContext 返回组件是否在 Router 的上下文环境中渲染的
useLinkClickHandler 获取 Link 的 click 事件句柄
useLoaderData 获取路由 loader 返回的数据, 当路由 loader 被调用之后, 数据将自动重新验证并从 loader 中返回最新结果
useLoaderData 不会启动获取, 只读取 React Router 内部管理的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import {StrictMode } from 'react' ;import {createRoot} from 'react-dom/client' ;import {useLoaderData, createBrowserRouter, createRoutesFromElements, RouterProvider } from 'react-router-dom' ;function Albums ( ){ const albums = useLoaderData (); return <div > Albums</div > ; } const router = createBrowserRouter (createRoutesFromElements ( <Route path ="/" element ={ <Albums /> } loader={async ({request, params}) => { return fakeFecth(); }} /> )); createRoot (document .getElementById ('root' )).render ( <StrictMode > <RouterProvider router ={router}/ > </StrictMode > )
useLocation 获取当前 location 的对象
location.hash
location.key
location.pathname
location.search
location.state 通过 <Link state/> 或者 navigate 创建的
useMatch 返回给定路径相对于当前位置上匹配的数据
动态路由参数分别传递给 loader , action , useParams
1 2 3 4 5 6 7 8 9 10 11 12 import {useMatch, useParams} from 'react-router-dom' ;function Random ( ){ const match = useMatch ('/projects/:projectId/tasks/:taskId' ); const params = useParams (); console .log (match.params .projectId ); console .log (match.params .taskId ); console .log (params.projectId ); console .log (params.taskId ); }
useMatches 获取当前页面匹配到的路由信息
useNavigate 返回一个 navigate 函数, 能够以编程式导航, 该函数接收两个参数
to 跳转的目标路由
options
replace
state
preventScrollReset
relative
1 2 3 4 5 6 7 8 9 10 11 12 import {useNavigate} from 'react-router-dom' ;function useLogoutTimer ( ){ const userIsInactive = useFakeInactive (); const navigate = useNavigate (); useEffect (() => { if (userIsInactive){ fake.logout (); navigate ('/session-time-out' , {state : {token : 'token' }}); } },[userIsInactive]); }
useNavigation 获取当前页面的所有导航信息
navigation.state
navigation.location
navigation.formData
navigation.json
navigation.text
navigation.formAction
navigation.formMethod
navigation.formEnctype
useNavigationType 返回当前页的导航类型
1 type NavigationType = 'POP' | 'PUSH' | 'REPLACE' ;
useParams 返回当前 url 中被 Route 匹配到的动态路由参数对象
动态路由参数分别传递给 loader , action , useMatch
1 2 3 4 5 6 7 function Books ( ){ const {id} = useParams (); } <Route path="/books/:id" element={<Books /> } />
useResolvedPath 返回给定 to 相对于当前位置的 pathname
useRevalidator 返回一个验证器对象, 允许重新验证数据
revalidator.state
revalidator.revalidate()
useRouteError 用在 errorElement 内部, 捕获由 action , loader , 或者渲染期间抛出的错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import {useRouteError, isRouteErrorResponse, Route , json} from 'react-router-dom' ;function ErrorBoundary ( ){ const error = useRouteError (); if (isRouteErrorResponse (error)){ return ( <div > <h1 > Oops!</h1 > <h2 > {error.status}</h2 > <p > {error.statusText}</p > {error.data?.message && <p > {error.data.message}</p > } </div > ) } else { return <div > Oops</div > ; } } <Route errorElement={<ErrorBoundary /> } action={async () => { throw json ( {message : 'email is required' }, {status : 400 } ) }} />
useRouteLoaderData 路由树上任何位置的当前渲染路线上的数据都可用, 对于树深层需要来自更高层路由的数据的组件以及需要树深层的子路由的数据的父路由非常有用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import {useRouteLoaderData} from 'react-router-dom' ;function SomeComp ( ){ const user = useRouteLoaderData ('root' ); } createBrowserRouter ([ { path : '/' , loader : () => fetchUser (), element : <Root /> id : 'root' , children : [ { path : 'jobs/:jobId' , loader : loaderJob, element : <JobListing /> } ] } ])
useRoutes 相当于 Routes 内置组件 的函数版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import {useRoutes, BrowserRouter } from 'react-router-dom' ;function App ( ){ const element = useRoutes ([ { path : '/' , element : <DashBoard /> , children : [ { path : 'message' , element : <DashBoardMessage /> }, { path : 'tasks' , element : <DashBoardTasks /> } ]}, { path : 'team' , element : <Team /> } ]); return ( <> <header > </header > <BrowserRouter > {element} </BrowserRouter > <footer > </footer > </> ) }
useSearchParams 读取或修改当前 URL 的参数部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import {useSearchParams} from 'react-router-dom' ;function App ( ){ const [searchParams, setSearchParams] = useSearchParams (); function handleSumbit (e ){ e.preventDefault (); const params = serializeFormQuery (e.target ); setSearchParams (params); } return ( <div > <form onSubmit ={handleSubmit} > <input type ="text" name ="username" /> </form > </div > ) }
useSubmit Form 表单提交的命令版本
submit(data, options?) 手动提交方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import {useSubmit, Form } from 'react-router-dom' ;function SearchFiled ( ){ let submit = useSubmit (); return ( <Form onChange ={(e) => { submit(null, {method: 'post', action: '/change'}); }}> <input type ="text" name ="search" /> <button type ="submit" > Search</button > </Form > ) }
React Router Utils json 格式化数据
1 2 3 4 5 6 import {json} from 'react-router-dom' ;const loader = async ( ) => { const data = fetchData (); return json (data); }
redirect 路由重定向
1 2 3 4 5 6 7 8 9 import {redirect} from 'react-router-dom' ;const loader = async ( ) => { const res = await fetch (); if (res.status == 401 ){ return redirect ('/login' ) } return null }
redirectDocument 触发一个文档级别的重定向, 而不是基于客户端导航, 通常用于从一个应用跳转到另一个应用
replace 导航跳转替换当前的历史记录栈
createRoutesFromElements 使用 JSX 元素创建路由, 简写形式是 createRoutesFromChildren
createSearchParams new URLSearchParams(init)
的包装写法
defer 延迟 loader 的返回值
1 2 3 4 5 6 7 import {defer} from 'react-router-dom' ;const loader = async ( ) => { let res = await fetch (); return defer ({name : 'zhangsan' , age : 18 }); }
generatePath 根据动态路由参数生成 url
1 2 3 import {generatePath} from 'react-router-dom' ;generatePath ('/users/:id/:name' , {id : 42 , name : 'zhangsan' });
isRouteErrorResponse 判断是否是由 useRouteError 捕获的路由错误
matchPath 将路由路径模式与 URL 路径进行匹配并返回有关的匹配信息, 否则返回 null
matchRoutes 执行一个路由匹配算法从给定的 routes 集合中找到匹配的路由并返回
renderMatches 渲染 matchRoutes 匹配结果中的 React 元素
resolvePath 根据给定的 to 解析为具有绝对路径的真实 path 对象
createPath
React Router v7 支持
根据传入的 路径、参数、哈希创建 URL
parsePath
React Router v7 支持
解析一个 URL, 作用 和 createPath 相反
data
React Router v7 支持
创建一个包含 status, headers 的 Response