router.d.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. import type { History, Location, Path, To } from "./history";
  2. import { Action as HistoryAction } from "./history";
  3. import type { AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticRouteObject, DataStrategyFunction, DeferredData, DetectErrorBoundaryFunction, FormEncType, HTMLFormMethod, MapRoutePropertiesFunction, RouteData, Submission, UIMatch, AgnosticPatchRoutesOnNavigationFunction, DataWithResponseInit } from "./utils";
  4. /**
  5. * A Router instance manages all navigation and data loading/mutations
  6. */
  7. export interface Router {
  8. /**
  9. * @internal
  10. * PRIVATE - DO NOT USE
  11. *
  12. * Return the basename for the router
  13. */
  14. get basename(): RouterInit["basename"];
  15. /**
  16. * @internal
  17. * PRIVATE - DO NOT USE
  18. *
  19. * Return the future config for the router
  20. */
  21. get future(): FutureConfig;
  22. /**
  23. * @internal
  24. * PRIVATE - DO NOT USE
  25. *
  26. * Return the current state of the router
  27. */
  28. get state(): RouterState;
  29. /**
  30. * @internal
  31. * PRIVATE - DO NOT USE
  32. *
  33. * Return the routes for this router instance
  34. */
  35. get routes(): AgnosticDataRouteObject[];
  36. /**
  37. * @internal
  38. * PRIVATE - DO NOT USE
  39. *
  40. * Return the window associated with the router
  41. */
  42. get window(): RouterInit["window"];
  43. /**
  44. * @internal
  45. * PRIVATE - DO NOT USE
  46. *
  47. * Initialize the router, including adding history listeners and kicking off
  48. * initial data fetches. Returns a function to cleanup listeners and abort
  49. * any in-progress loads
  50. */
  51. initialize(): Router;
  52. /**
  53. * @internal
  54. * PRIVATE - DO NOT USE
  55. *
  56. * Subscribe to router.state updates
  57. *
  58. * @param fn function to call with the new state
  59. */
  60. subscribe(fn: RouterSubscriber): () => void;
  61. /**
  62. * @internal
  63. * PRIVATE - DO NOT USE
  64. *
  65. * Enable scroll restoration behavior in the router
  66. *
  67. * @param savedScrollPositions Object that will manage positions, in case
  68. * it's being restored from sessionStorage
  69. * @param getScrollPosition Function to get the active Y scroll position
  70. * @param getKey Function to get the key to use for restoration
  71. */
  72. enableScrollRestoration(savedScrollPositions: Record<string, number>, getScrollPosition: GetScrollPositionFunction, getKey?: GetScrollRestorationKeyFunction): () => void;
  73. /**
  74. * @internal
  75. * PRIVATE - DO NOT USE
  76. *
  77. * Navigate forward/backward in the history stack
  78. * @param to Delta to move in the history stack
  79. */
  80. navigate(to: number): Promise<void>;
  81. /**
  82. * Navigate to the given path
  83. * @param to Path to navigate to
  84. * @param opts Navigation options (method, submission, etc.)
  85. */
  86. navigate(to: To | null, opts?: RouterNavigateOptions): Promise<void>;
  87. /**
  88. * @internal
  89. * PRIVATE - DO NOT USE
  90. *
  91. * Trigger a fetcher load/submission
  92. *
  93. * @param key Fetcher key
  94. * @param routeId Route that owns the fetcher
  95. * @param href href to fetch
  96. * @param opts Fetcher options, (method, submission, etc.)
  97. */
  98. fetch(key: string, routeId: string, href: string | null, opts?: RouterFetchOptions): void;
  99. /**
  100. * @internal
  101. * PRIVATE - DO NOT USE
  102. *
  103. * Trigger a revalidation of all current route loaders and fetcher loads
  104. */
  105. revalidate(): void;
  106. /**
  107. * @internal
  108. * PRIVATE - DO NOT USE
  109. *
  110. * Utility function to create an href for the given location
  111. * @param location
  112. */
  113. createHref(location: Location | URL): string;
  114. /**
  115. * @internal
  116. * PRIVATE - DO NOT USE
  117. *
  118. * Utility function to URL encode a destination path according to the internal
  119. * history implementation
  120. * @param to
  121. */
  122. encodeLocation(to: To): Path;
  123. /**
  124. * @internal
  125. * PRIVATE - DO NOT USE
  126. *
  127. * Get/create a fetcher for the given key
  128. * @param key
  129. */
  130. getFetcher<TData = any>(key: string): Fetcher<TData>;
  131. /**
  132. * @internal
  133. * PRIVATE - DO NOT USE
  134. *
  135. * Delete the fetcher for a given key
  136. * @param key
  137. */
  138. deleteFetcher(key: string): void;
  139. /**
  140. * @internal
  141. * PRIVATE - DO NOT USE
  142. *
  143. * Cleanup listeners and abort any in-progress loads
  144. */
  145. dispose(): void;
  146. /**
  147. * @internal
  148. * PRIVATE - DO NOT USE
  149. *
  150. * Get a navigation blocker
  151. * @param key The identifier for the blocker
  152. * @param fn The blocker function implementation
  153. */
  154. getBlocker(key: string, fn: BlockerFunction): Blocker;
  155. /**
  156. * @internal
  157. * PRIVATE - DO NOT USE
  158. *
  159. * Delete a navigation blocker
  160. * @param key The identifier for the blocker
  161. */
  162. deleteBlocker(key: string): void;
  163. /**
  164. * @internal
  165. * PRIVATE DO NOT USE
  166. *
  167. * Patch additional children routes into an existing parent route
  168. * @param routeId The parent route id or a callback function accepting `patch`
  169. * to perform batch patching
  170. * @param children The additional children routes
  171. */
  172. patchRoutes(routeId: string | null, children: AgnosticRouteObject[]): void;
  173. /**
  174. * @internal
  175. * PRIVATE - DO NOT USE
  176. *
  177. * HMR needs to pass in-flight route updates to React Router
  178. * TODO: Replace this with granular route update APIs (addRoute, updateRoute, deleteRoute)
  179. */
  180. _internalSetRoutes(routes: AgnosticRouteObject[]): void;
  181. /**
  182. * @internal
  183. * PRIVATE - DO NOT USE
  184. *
  185. * Internal fetch AbortControllers accessed by unit tests
  186. */
  187. _internalFetchControllers: Map<string, AbortController>;
  188. /**
  189. * @internal
  190. * PRIVATE - DO NOT USE
  191. *
  192. * Internal pending DeferredData instances accessed by unit tests
  193. */
  194. _internalActiveDeferreds: Map<string, DeferredData>;
  195. }
  196. /**
  197. * State maintained internally by the router. During a navigation, all states
  198. * reflect the the "old" location unless otherwise noted.
  199. */
  200. export interface RouterState {
  201. /**
  202. * The action of the most recent navigation
  203. */
  204. historyAction: HistoryAction;
  205. /**
  206. * The current location reflected by the router
  207. */
  208. location: Location;
  209. /**
  210. * The current set of route matches
  211. */
  212. matches: AgnosticDataRouteMatch[];
  213. /**
  214. * Tracks whether we've completed our initial data load
  215. */
  216. initialized: boolean;
  217. /**
  218. * Current scroll position we should start at for a new view
  219. * - number -> scroll position to restore to
  220. * - false -> do not restore scroll at all (used during submissions)
  221. * - null -> don't have a saved position, scroll to hash or top of page
  222. */
  223. restoreScrollPosition: number | false | null;
  224. /**
  225. * Indicate whether this navigation should skip resetting the scroll position
  226. * if we are unable to restore the scroll position
  227. */
  228. preventScrollReset: boolean;
  229. /**
  230. * Tracks the state of the current navigation
  231. */
  232. navigation: Navigation;
  233. /**
  234. * Tracks any in-progress revalidations
  235. */
  236. revalidation: RevalidationState;
  237. /**
  238. * Data from the loaders for the current matches
  239. */
  240. loaderData: RouteData;
  241. /**
  242. * Data from the action for the current matches
  243. */
  244. actionData: RouteData | null;
  245. /**
  246. * Errors caught from loaders for the current matches
  247. */
  248. errors: RouteData | null;
  249. /**
  250. * Map of current fetchers
  251. */
  252. fetchers: Map<string, Fetcher>;
  253. /**
  254. * Map of current blockers
  255. */
  256. blockers: Map<string, Blocker>;
  257. }
  258. /**
  259. * Data that can be passed into hydrate a Router from SSR
  260. */
  261. export type HydrationState = Partial<Pick<RouterState, "loaderData" | "actionData" | "errors">>;
  262. /**
  263. * Future flags to toggle new feature behavior
  264. */
  265. export interface FutureConfig {
  266. v7_fetcherPersist: boolean;
  267. v7_normalizeFormMethod: boolean;
  268. v7_partialHydration: boolean;
  269. v7_prependBasename: boolean;
  270. v7_relativeSplatPath: boolean;
  271. v7_skipActionErrorRevalidation: boolean;
  272. }
  273. /**
  274. * Initialization options for createRouter
  275. */
  276. export interface RouterInit {
  277. routes: AgnosticRouteObject[];
  278. history: History;
  279. basename?: string;
  280. /**
  281. * @deprecated Use `mapRouteProperties` instead
  282. */
  283. detectErrorBoundary?: DetectErrorBoundaryFunction;
  284. mapRouteProperties?: MapRoutePropertiesFunction;
  285. future?: Partial<FutureConfig>;
  286. hydrationData?: HydrationState;
  287. window?: Window;
  288. dataStrategy?: DataStrategyFunction;
  289. patchRoutesOnNavigation?: AgnosticPatchRoutesOnNavigationFunction;
  290. }
  291. /**
  292. * State returned from a server-side query() call
  293. */
  294. export interface StaticHandlerContext {
  295. basename: Router["basename"];
  296. location: RouterState["location"];
  297. matches: RouterState["matches"];
  298. loaderData: RouterState["loaderData"];
  299. actionData: RouterState["actionData"];
  300. errors: RouterState["errors"];
  301. statusCode: number;
  302. loaderHeaders: Record<string, Headers>;
  303. actionHeaders: Record<string, Headers>;
  304. activeDeferreds: Record<string, DeferredData> | null;
  305. _deepestRenderedBoundaryId?: string | null;
  306. }
  307. /**
  308. * A StaticHandler instance manages a singular SSR navigation/fetch event
  309. */
  310. export interface StaticHandler {
  311. dataRoutes: AgnosticDataRouteObject[];
  312. query(request: Request, opts?: {
  313. requestContext?: unknown;
  314. skipLoaderErrorBubbling?: boolean;
  315. dataStrategy?: DataStrategyFunction;
  316. }): Promise<StaticHandlerContext | Response>;
  317. queryRoute(request: Request, opts?: {
  318. routeId?: string;
  319. requestContext?: unknown;
  320. dataStrategy?: DataStrategyFunction;
  321. }): Promise<any>;
  322. }
  323. type ViewTransitionOpts = {
  324. currentLocation: Location;
  325. nextLocation: Location;
  326. };
  327. /**
  328. * Subscriber function signature for changes to router state
  329. */
  330. export interface RouterSubscriber {
  331. (state: RouterState, opts: {
  332. deletedFetchers: string[];
  333. viewTransitionOpts?: ViewTransitionOpts;
  334. flushSync: boolean;
  335. }): void;
  336. }
  337. /**
  338. * Function signature for determining the key to be used in scroll restoration
  339. * for a given location
  340. */
  341. export interface GetScrollRestorationKeyFunction {
  342. (location: Location, matches: UIMatch[]): string | null;
  343. }
  344. /**
  345. * Function signature for determining the current scroll position
  346. */
  347. export interface GetScrollPositionFunction {
  348. (): number;
  349. }
  350. export type RelativeRoutingType = "route" | "path";
  351. type BaseNavigateOrFetchOptions = {
  352. preventScrollReset?: boolean;
  353. relative?: RelativeRoutingType;
  354. flushSync?: boolean;
  355. };
  356. type BaseNavigateOptions = BaseNavigateOrFetchOptions & {
  357. replace?: boolean;
  358. state?: any;
  359. fromRouteId?: string;
  360. viewTransition?: boolean;
  361. };
  362. type BaseSubmissionOptions = {
  363. formMethod?: HTMLFormMethod;
  364. formEncType?: FormEncType;
  365. } & ({
  366. formData: FormData;
  367. body?: undefined;
  368. } | {
  369. formData?: undefined;
  370. body: any;
  371. });
  372. /**
  373. * Options for a navigate() call for a normal (non-submission) navigation
  374. */
  375. type LinkNavigateOptions = BaseNavigateOptions;
  376. /**
  377. * Options for a navigate() call for a submission navigation
  378. */
  379. type SubmissionNavigateOptions = BaseNavigateOptions & BaseSubmissionOptions;
  380. /**
  381. * Options to pass to navigate() for a navigation
  382. */
  383. export type RouterNavigateOptions = LinkNavigateOptions | SubmissionNavigateOptions;
  384. /**
  385. * Options for a fetch() load
  386. */
  387. type LoadFetchOptions = BaseNavigateOrFetchOptions;
  388. /**
  389. * Options for a fetch() submission
  390. */
  391. type SubmitFetchOptions = BaseNavigateOrFetchOptions & BaseSubmissionOptions;
  392. /**
  393. * Options to pass to fetch()
  394. */
  395. export type RouterFetchOptions = LoadFetchOptions | SubmitFetchOptions;
  396. /**
  397. * Potential states for state.navigation
  398. */
  399. export type NavigationStates = {
  400. Idle: {
  401. state: "idle";
  402. location: undefined;
  403. formMethod: undefined;
  404. formAction: undefined;
  405. formEncType: undefined;
  406. formData: undefined;
  407. json: undefined;
  408. text: undefined;
  409. };
  410. Loading: {
  411. state: "loading";
  412. location: Location;
  413. formMethod: Submission["formMethod"] | undefined;
  414. formAction: Submission["formAction"] | undefined;
  415. formEncType: Submission["formEncType"] | undefined;
  416. formData: Submission["formData"] | undefined;
  417. json: Submission["json"] | undefined;
  418. text: Submission["text"] | undefined;
  419. };
  420. Submitting: {
  421. state: "submitting";
  422. location: Location;
  423. formMethod: Submission["formMethod"];
  424. formAction: Submission["formAction"];
  425. formEncType: Submission["formEncType"];
  426. formData: Submission["formData"];
  427. json: Submission["json"];
  428. text: Submission["text"];
  429. };
  430. };
  431. export type Navigation = NavigationStates[keyof NavigationStates];
  432. export type RevalidationState = "idle" | "loading";
  433. /**
  434. * Potential states for fetchers
  435. */
  436. type FetcherStates<TData = any> = {
  437. Idle: {
  438. state: "idle";
  439. formMethod: undefined;
  440. formAction: undefined;
  441. formEncType: undefined;
  442. text: undefined;
  443. formData: undefined;
  444. json: undefined;
  445. data: TData | undefined;
  446. };
  447. Loading: {
  448. state: "loading";
  449. formMethod: Submission["formMethod"] | undefined;
  450. formAction: Submission["formAction"] | undefined;
  451. formEncType: Submission["formEncType"] | undefined;
  452. text: Submission["text"] | undefined;
  453. formData: Submission["formData"] | undefined;
  454. json: Submission["json"] | undefined;
  455. data: TData | undefined;
  456. };
  457. Submitting: {
  458. state: "submitting";
  459. formMethod: Submission["formMethod"];
  460. formAction: Submission["formAction"];
  461. formEncType: Submission["formEncType"];
  462. text: Submission["text"];
  463. formData: Submission["formData"];
  464. json: Submission["json"];
  465. data: TData | undefined;
  466. };
  467. };
  468. export type Fetcher<TData = any> = FetcherStates<TData>[keyof FetcherStates<TData>];
  469. interface BlockerBlocked {
  470. state: "blocked";
  471. reset(): void;
  472. proceed(): void;
  473. location: Location;
  474. }
  475. interface BlockerUnblocked {
  476. state: "unblocked";
  477. reset: undefined;
  478. proceed: undefined;
  479. location: undefined;
  480. }
  481. interface BlockerProceeding {
  482. state: "proceeding";
  483. reset: undefined;
  484. proceed: undefined;
  485. location: Location;
  486. }
  487. export type Blocker = BlockerUnblocked | BlockerBlocked | BlockerProceeding;
  488. export type BlockerFunction = (args: {
  489. currentLocation: Location;
  490. nextLocation: Location;
  491. historyAction: HistoryAction;
  492. }) => boolean;
  493. export declare const IDLE_NAVIGATION: NavigationStates["Idle"];
  494. export declare const IDLE_FETCHER: FetcherStates["Idle"];
  495. export declare const IDLE_BLOCKER: BlockerUnblocked;
  496. /**
  497. * Create a router and listen to history POP navigations
  498. */
  499. export declare function createRouter(init: RouterInit): Router;
  500. export declare const UNSAFE_DEFERRED_SYMBOL: unique symbol;
  501. /**
  502. * Future flags to toggle new feature behavior
  503. */
  504. export interface StaticHandlerFutureConfig {
  505. v7_relativeSplatPath: boolean;
  506. v7_throwAbortReason: boolean;
  507. }
  508. export interface CreateStaticHandlerOptions {
  509. basename?: string;
  510. /**
  511. * @deprecated Use `mapRouteProperties` instead
  512. */
  513. detectErrorBoundary?: DetectErrorBoundaryFunction;
  514. mapRouteProperties?: MapRoutePropertiesFunction;
  515. future?: Partial<StaticHandlerFutureConfig>;
  516. }
  517. export declare function createStaticHandler(routes: AgnosticRouteObject[], opts?: CreateStaticHandlerOptions): StaticHandler;
  518. /**
  519. * Given an existing StaticHandlerContext and an error thrown at render time,
  520. * provide an updated StaticHandlerContext suitable for a second SSR render
  521. */
  522. export declare function getStaticContextFromError(routes: AgnosticDataRouteObject[], context: StaticHandlerContext, error: any): StaticHandlerContext;
  523. export declare function isDataWithResponseInit(value: any): value is DataWithResponseInit<unknown>;
  524. export declare function isDeferredData(value: any): value is DeferredData;
  525. export {};