react-router 7.15.1 → 8.0.0-pre.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (369) hide show
  1. package/CHANGELOG.md +18 -2
  2. package/dist/development/dom-export.d.ts +6 -172
  3. package/dist/development/dom-export.js +12 -1007
  4. package/dist/development/index-react-server-client.d.ts +7 -4
  5. package/dist/development/index-react-server-client.js +8 -52
  6. package/dist/development/index-react-server.d.ts +1645 -1635
  7. package/dist/development/index-react-server.js +2880 -3642
  8. package/dist/development/index.d.ts +43 -1469
  9. package/dist/development/index.js +37 -2621
  10. package/dist/development/lib/actions.js +62 -0
  11. package/dist/development/lib/components.d.ts +1022 -0
  12. package/dist/development/lib/components.js +835 -0
  13. package/dist/development/lib/context.d.ts +83 -0
  14. package/dist/development/lib/context.js +41 -0
  15. package/dist/development/lib/dom/dom.d.ts +119 -0
  16. package/dist/development/lib/dom/dom.js +143 -0
  17. package/dist/development/lib/dom/lib.d.ts +2042 -0
  18. package/dist/development/lib/dom/lib.js +1259 -0
  19. package/dist/development/lib/dom/server.d.ts +138 -0
  20. package/dist/development/lib/dom/server.js +301 -0
  21. package/dist/development/lib/dom/ssr/components.d.ts +196 -0
  22. package/dist/development/lib/dom/ssr/components.js +579 -0
  23. package/dist/development/lib/dom/ssr/data.js +29 -0
  24. package/dist/development/lib/dom/ssr/entry.d.ts +59 -0
  25. package/dist/development/lib/dom/ssr/errorBoundaries.d.ts +27 -0
  26. package/dist/development/lib/dom/ssr/errorBoundaries.js +83 -0
  27. package/dist/development/lib/dom/ssr/errors.d.ts +7 -0
  28. package/dist/development/lib/dom/ssr/errors.js +36 -0
  29. package/dist/development/lib/dom/ssr/fallback.js +28 -0
  30. package/dist/development/lib/dom/ssr/fog-of-war.d.ts +12 -0
  31. package/dist/development/lib/dom/ssr/fog-of-war.js +170 -0
  32. package/dist/development/lib/dom/ssr/hydration.d.ts +32 -0
  33. package/dist/development/lib/dom/ssr/hydration.js +29 -0
  34. package/dist/development/lib/dom/ssr/invariant.js +16 -0
  35. package/dist/development/lib/dom/ssr/links.js +170 -0
  36. package/dist/development/lib/dom/ssr/markup.js +24 -0
  37. package/dist/development/lib/dom/ssr/routeModules.d.ts +206 -0
  38. package/dist/development/lib/dom/ssr/routeModules.js +31 -0
  39. package/dist/development/lib/dom/ssr/routes-test-stub.d.ts +62 -0
  40. package/dist/development/lib/dom/ssr/routes-test-stub.js +108 -0
  41. package/dist/development/lib/dom/ssr/routes.d.ts +33 -0
  42. package/dist/development/lib/dom/ssr/routes.js +303 -0
  43. package/dist/development/lib/dom/ssr/server.d.ts +45 -0
  44. package/dist/development/lib/dom/ssr/server.js +68 -0
  45. package/dist/development/lib/dom/ssr/single-fetch.d.ts +14 -0
  46. package/dist/development/lib/dom/ssr/single-fetch.js +346 -0
  47. package/dist/development/lib/dom-export/dom-router-provider.d.ts +9 -0
  48. package/dist/development/lib/dom-export/dom-router-provider.js +22 -0
  49. package/dist/development/lib/dom-export/hydrated-router.d.ts +125 -0
  50. package/dist/development/lib/dom-export/hydrated-router.js +153 -0
  51. package/dist/development/lib/errors.js +29 -0
  52. package/dist/development/lib/hooks.d.ts +947 -0
  53. package/dist/development/lib/hooks.js +1386 -0
  54. package/dist/development/lib/href.d.ts +20 -0
  55. package/dist/development/lib/href.js +50 -0
  56. package/dist/development/lib/router/history.d.ts +258 -0
  57. package/dist/development/lib/router/history.js +371 -0
  58. package/dist/development/lib/router/instrumentation.d.ts +86 -0
  59. package/dist/development/lib/router/instrumentation.js +213 -0
  60. package/dist/development/lib/router/links.d.ts +113 -0
  61. package/dist/development/lib/router/router.d.ts +663 -0
  62. package/dist/development/lib/router/router.js +2981 -0
  63. package/dist/development/lib/router/utils.d.ts +942 -0
  64. package/dist/development/lib/router/utils.js +791 -0
  65. package/dist/development/lib/rsc/browser.d.ts +137 -0
  66. package/dist/development/lib/rsc/browser.js +599 -0
  67. package/dist/development/lib/rsc/errorBoundaries.d.ts +11 -0
  68. package/dist/development/lib/rsc/errorBoundaries.js +90 -0
  69. package/dist/development/lib/rsc/html-stream/browser.d.ts +48 -0
  70. package/dist/development/lib/rsc/html-stream/browser.js +74 -0
  71. package/dist/development/lib/rsc/html-stream/server.js +78 -0
  72. package/dist/development/lib/rsc/route-modules.js +27 -0
  73. package/dist/development/lib/rsc/server.rsc.d.ts +219 -0
  74. package/dist/development/lib/rsc/server.ssr.d.ts +129 -0
  75. package/dist/development/lib/rsc/server.ssr.js +388 -0
  76. package/dist/development/lib/server-runtime/build.d.ts +66 -0
  77. package/dist/development/lib/server-runtime/cookies.d.ts +66 -0
  78. package/dist/development/lib/server-runtime/cookies.js +139 -0
  79. package/dist/development/lib/server-runtime/crypto.js +43 -0
  80. package/dist/development/lib/server-runtime/data.d.ts +13 -0
  81. package/dist/development/lib/server-runtime/data.js +25 -0
  82. package/dist/development/lib/server-runtime/dev.d.ts +9 -0
  83. package/dist/development/lib/server-runtime/dev.js +26 -0
  84. package/dist/development/lib/server-runtime/entry.js +20 -0
  85. package/dist/development/lib/server-runtime/errors.js +95 -0
  86. package/dist/development/lib/server-runtime/headers.js +73 -0
  87. package/dist/development/lib/server-runtime/invariant.js +19 -0
  88. package/dist/development/lib/server-runtime/mode.d.ts +12 -0
  89. package/dist/development/lib/server-runtime/mode.js +25 -0
  90. package/dist/development/lib/server-runtime/routeMatching.js +28 -0
  91. package/dist/development/lib/server-runtime/routes.d.ts +13 -0
  92. package/dist/development/lib/server-runtime/routes.js +74 -0
  93. package/dist/development/lib/server-runtime/server.d.ts +10 -0
  94. package/dist/development/lib/server-runtime/server.js +351 -0
  95. package/dist/development/lib/server-runtime/serverHandoff.js +17 -0
  96. package/dist/development/lib/server-runtime/sessions/cookieStorage.d.ts +25 -0
  97. package/dist/development/lib/server-runtime/sessions/cookieStorage.js +45 -0
  98. package/dist/development/lib/server-runtime/sessions/memoryStorage.d.ts +23 -0
  99. package/dist/development/lib/server-runtime/sessions/memoryStorage.js +52 -0
  100. package/dist/development/lib/server-runtime/sessions.d.ts +145 -0
  101. package/dist/development/lib/server-runtime/sessions.js +98 -0
  102. package/dist/development/lib/server-runtime/single-fetch.d.ts +7 -0
  103. package/dist/development/lib/server-runtime/single-fetch.js +215 -0
  104. package/dist/development/lib/server-runtime/urls.js +31 -0
  105. package/dist/development/lib/server-runtime/warnings.js +20 -0
  106. package/dist/development/lib/types/future.d.ts +9 -0
  107. package/dist/development/lib/types/internal.d.ts +26 -177
  108. package/dist/development/lib/types/internal.js +3 -2
  109. package/dist/{production/register-Bsscfj79.d.ts → development/lib/types/register.d.ts} +9 -15
  110. package/dist/development/lib/types/route-data.d.ts +113 -0
  111. package/dist/development/lib/types/route-module-annotations.d.ts +149 -0
  112. package/dist/development/lib/types/route-module.d.ts +19 -0
  113. package/dist/development/lib/types/serializes-to.d.ts +13 -0
  114. package/dist/development/lib/types/utils.d.ts +11 -0
  115. package/dist/development/vendor/turbo-stream-v2/flatten.js +159 -0
  116. package/dist/development/vendor/turbo-stream-v2/turbo-stream.js +178 -0
  117. package/dist/development/vendor/turbo-stream-v2/unflatten.js +198 -0
  118. package/dist/development/vendor/turbo-stream-v2/utils.js +47 -0
  119. package/dist/production/dom-export.d.ts +6 -172
  120. package/dist/production/dom-export.js +12 -1007
  121. package/dist/production/index-react-server-client.d.ts +7 -4
  122. package/dist/production/index-react-server-client.js +8 -52
  123. package/dist/production/index-react-server.d.ts +1645 -1635
  124. package/dist/production/index-react-server.js +2871 -3642
  125. package/dist/production/index.d.ts +43 -1469
  126. package/dist/production/index.js +37 -2621
  127. package/dist/production/lib/actions.js +62 -0
  128. package/dist/production/lib/components.d.ts +1022 -0
  129. package/dist/production/lib/components.js +835 -0
  130. package/dist/production/lib/context.d.ts +83 -0
  131. package/dist/production/lib/context.js +41 -0
  132. package/dist/production/lib/dom/dom.d.ts +119 -0
  133. package/dist/production/lib/dom/dom.js +143 -0
  134. package/dist/production/lib/dom/lib.d.ts +2042 -0
  135. package/dist/production/lib/dom/lib.js +1259 -0
  136. package/dist/production/lib/dom/server.d.ts +138 -0
  137. package/dist/production/lib/dom/server.js +301 -0
  138. package/dist/production/lib/dom/ssr/components.d.ts +196 -0
  139. package/dist/production/lib/dom/ssr/components.js +579 -0
  140. package/dist/production/lib/dom/ssr/data.js +29 -0
  141. package/dist/production/lib/dom/ssr/entry.d.ts +59 -0
  142. package/dist/production/lib/dom/ssr/errorBoundaries.d.ts +27 -0
  143. package/dist/production/lib/dom/ssr/errorBoundaries.js +83 -0
  144. package/dist/production/lib/dom/ssr/errors.d.ts +7 -0
  145. package/dist/production/lib/dom/ssr/errors.js +36 -0
  146. package/dist/production/lib/dom/ssr/fallback.js +21 -0
  147. package/dist/production/lib/dom/ssr/fog-of-war.d.ts +12 -0
  148. package/dist/production/lib/dom/ssr/fog-of-war.js +170 -0
  149. package/dist/production/lib/dom/ssr/hydration.d.ts +32 -0
  150. package/dist/production/lib/dom/ssr/hydration.js +29 -0
  151. package/dist/production/lib/dom/ssr/invariant.js +16 -0
  152. package/dist/production/lib/dom/ssr/links.js +170 -0
  153. package/dist/production/lib/dom/ssr/markup.js +24 -0
  154. package/dist/production/lib/dom/ssr/routeModules.d.ts +206 -0
  155. package/dist/production/lib/dom/ssr/routeModules.js +31 -0
  156. package/dist/production/lib/dom/ssr/routes-test-stub.d.ts +62 -0
  157. package/dist/production/lib/dom/ssr/routes-test-stub.js +108 -0
  158. package/dist/production/lib/dom/ssr/routes.d.ts +33 -0
  159. package/dist/production/lib/dom/ssr/routes.js +303 -0
  160. package/dist/production/lib/dom/ssr/server.d.ts +45 -0
  161. package/dist/production/lib/dom/ssr/server.js +68 -0
  162. package/dist/production/lib/dom/ssr/single-fetch.d.ts +14 -0
  163. package/dist/production/lib/dom/ssr/single-fetch.js +346 -0
  164. package/dist/production/lib/dom-export/dom-router-provider.d.ts +9 -0
  165. package/dist/production/lib/dom-export/dom-router-provider.js +22 -0
  166. package/dist/production/lib/dom-export/hydrated-router.d.ts +125 -0
  167. package/dist/production/lib/dom-export/hydrated-router.js +153 -0
  168. package/dist/production/lib/errors.js +29 -0
  169. package/dist/production/lib/hooks.d.ts +947 -0
  170. package/dist/production/lib/hooks.js +1371 -0
  171. package/dist/production/lib/href.d.ts +20 -0
  172. package/dist/production/lib/href.js +50 -0
  173. package/dist/production/lib/router/history.d.ts +258 -0
  174. package/dist/production/lib/router/history.js +371 -0
  175. package/dist/production/lib/router/instrumentation.d.ts +86 -0
  176. package/dist/production/lib/router/instrumentation.js +213 -0
  177. package/dist/production/lib/router/links.d.ts +113 -0
  178. package/dist/production/lib/router/router.d.ts +663 -0
  179. package/dist/production/lib/router/router.js +2981 -0
  180. package/dist/production/lib/router/utils.d.ts +942 -0
  181. package/dist/production/lib/router/utils.js +782 -0
  182. package/dist/production/lib/rsc/browser.d.ts +137 -0
  183. package/dist/production/lib/rsc/browser.js +599 -0
  184. package/dist/production/lib/rsc/errorBoundaries.d.ts +11 -0
  185. package/dist/production/lib/rsc/errorBoundaries.js +90 -0
  186. package/dist/production/lib/rsc/html-stream/browser.d.ts +48 -0
  187. package/dist/production/lib/rsc/html-stream/browser.js +74 -0
  188. package/dist/production/lib/rsc/html-stream/server.js +78 -0
  189. package/dist/production/lib/rsc/route-modules.js +27 -0
  190. package/dist/production/lib/rsc/server.rsc.d.ts +219 -0
  191. package/dist/production/lib/rsc/server.ssr.d.ts +129 -0
  192. package/dist/production/lib/rsc/server.ssr.js +388 -0
  193. package/dist/production/lib/server-runtime/build.d.ts +66 -0
  194. package/dist/production/lib/server-runtime/cookies.d.ts +66 -0
  195. package/dist/production/lib/server-runtime/cookies.js +139 -0
  196. package/dist/production/lib/server-runtime/crypto.js +43 -0
  197. package/dist/production/lib/server-runtime/data.d.ts +13 -0
  198. package/dist/production/lib/server-runtime/data.js +25 -0
  199. package/dist/production/lib/server-runtime/dev.d.ts +9 -0
  200. package/dist/production/lib/server-runtime/dev.js +26 -0
  201. package/dist/production/lib/server-runtime/entry.js +20 -0
  202. package/dist/production/lib/server-runtime/errors.js +95 -0
  203. package/dist/production/lib/server-runtime/headers.js +73 -0
  204. package/dist/production/lib/server-runtime/invariant.js +19 -0
  205. package/dist/production/lib/server-runtime/mode.d.ts +12 -0
  206. package/dist/production/lib/server-runtime/mode.js +25 -0
  207. package/dist/production/lib/server-runtime/routeMatching.js +28 -0
  208. package/dist/production/lib/server-runtime/routes.d.ts +13 -0
  209. package/dist/production/lib/server-runtime/routes.js +74 -0
  210. package/dist/production/lib/server-runtime/server.d.ts +10 -0
  211. package/dist/production/lib/server-runtime/server.js +351 -0
  212. package/dist/production/lib/server-runtime/serverHandoff.js +17 -0
  213. package/dist/production/lib/server-runtime/sessions/cookieStorage.d.ts +25 -0
  214. package/dist/production/lib/server-runtime/sessions/cookieStorage.js +45 -0
  215. package/dist/production/lib/server-runtime/sessions/memoryStorage.d.ts +23 -0
  216. package/dist/production/lib/server-runtime/sessions/memoryStorage.js +52 -0
  217. package/dist/production/lib/server-runtime/sessions.d.ts +145 -0
  218. package/dist/production/lib/server-runtime/sessions.js +98 -0
  219. package/dist/production/lib/server-runtime/single-fetch.d.ts +7 -0
  220. package/dist/production/lib/server-runtime/single-fetch.js +215 -0
  221. package/dist/production/lib/server-runtime/urls.js +31 -0
  222. package/dist/production/lib/server-runtime/warnings.js +20 -0
  223. package/dist/production/lib/types/future.d.ts +9 -0
  224. package/dist/production/lib/types/internal.d.ts +26 -177
  225. package/dist/production/lib/types/internal.js +3 -2
  226. package/dist/{development/register-Bsscfj79.d.ts → production/lib/types/register.d.ts} +9 -15
  227. package/dist/production/lib/types/route-data.d.ts +113 -0
  228. package/dist/production/lib/types/route-module-annotations.d.ts +149 -0
  229. package/dist/production/lib/types/route-module.d.ts +19 -0
  230. package/dist/production/lib/types/serializes-to.d.ts +13 -0
  231. package/dist/production/lib/types/utils.d.ts +11 -0
  232. package/dist/production/vendor/turbo-stream-v2/flatten.js +159 -0
  233. package/dist/production/vendor/turbo-stream-v2/turbo-stream.js +178 -0
  234. package/dist/production/vendor/turbo-stream-v2/unflatten.js +198 -0
  235. package/dist/production/vendor/turbo-stream-v2/utils.js +47 -0
  236. package/docs/explanation/backend-for-frontend.md +50 -0
  237. package/docs/explanation/code-splitting.md +77 -0
  238. package/docs/explanation/concurrency.md +135 -0
  239. package/docs/explanation/form-vs-fetcher.md +292 -0
  240. package/docs/explanation/hot-module-replacement.md +137 -0
  241. package/docs/explanation/hydration.md +14 -0
  242. package/docs/explanation/index-query-param.md +86 -0
  243. package/docs/explanation/index.md +4 -0
  244. package/docs/explanation/lazy-route-discovery.md +78 -0
  245. package/docs/explanation/location.md +6 -0
  246. package/docs/explanation/progressive-enhancement.md +150 -0
  247. package/docs/explanation/race-conditions.md +88 -0
  248. package/docs/explanation/react-transitions.md +160 -0
  249. package/docs/explanation/route-matching.md +7 -0
  250. package/docs/explanation/server-client-execution.md +4 -0
  251. package/docs/explanation/sessions-and-cookies.md +465 -0
  252. package/docs/explanation/special-files.md +16 -0
  253. package/docs/explanation/state-management.md +524 -0
  254. package/docs/explanation/styling.md +87 -0
  255. package/docs/explanation/type-safety.md +82 -0
  256. package/docs/how-to/accessibility.md +44 -0
  257. package/docs/how-to/client-data.md +199 -0
  258. package/docs/how-to/data-strategy.md +317 -0
  259. package/docs/how-to/error-boundary.md +231 -0
  260. package/docs/how-to/error-reporting.md +134 -0
  261. package/docs/how-to/fetchers.md +307 -0
  262. package/docs/how-to/file-route-conventions.md +410 -0
  263. package/docs/how-to/file-uploads.md +217 -0
  264. package/docs/how-to/form-validation.md +120 -0
  265. package/docs/how-to/headers.md +164 -0
  266. package/docs/how-to/index.md +4 -0
  267. package/docs/how-to/instrumentation.md +556 -0
  268. package/docs/how-to/meta.md +40 -0
  269. package/docs/how-to/middleware.md +728 -0
  270. package/docs/how-to/navigation-blocking.md +233 -0
  271. package/docs/how-to/optimize-revalidation.md +12 -0
  272. package/docs/how-to/pre-rendering.md +225 -0
  273. package/docs/how-to/presets.md +103 -0
  274. package/docs/how-to/react-server-components.md +899 -0
  275. package/docs/how-to/resource-routes.md +126 -0
  276. package/docs/how-to/route-module-type-safety.md +100 -0
  277. package/docs/how-to/search-params.md +4 -0
  278. package/docs/how-to/security.md +30 -0
  279. package/docs/how-to/server-bundles.md +66 -0
  280. package/docs/how-to/spa.md +120 -0
  281. package/docs/how-to/status.md +63 -0
  282. package/docs/how-to/suspense.md +132 -0
  283. package/docs/how-to/using-handle.md +117 -0
  284. package/docs/how-to/view-transitions.md +237 -0
  285. package/docs/how-to/webhook.md +50 -0
  286. package/docs/index.md +39 -0
  287. package/docs/start/data/actions.md +138 -0
  288. package/docs/start/data/custom.md +198 -0
  289. package/docs/start/data/data-loading.md +44 -0
  290. package/docs/start/data/index.md +4 -0
  291. package/docs/start/data/installation.md +52 -0
  292. package/docs/start/data/navigating.md +12 -0
  293. package/docs/start/data/pending-ui.md +12 -0
  294. package/docs/start/data/route-object.md +248 -0
  295. package/docs/start/data/routing.md +281 -0
  296. package/docs/start/data/testing.md +8 -0
  297. package/docs/start/declarative/index.md +4 -0
  298. package/docs/start/declarative/installation.md +43 -0
  299. package/docs/start/declarative/navigating.md +133 -0
  300. package/docs/start/declarative/routing.md +237 -0
  301. package/docs/start/declarative/url-values.md +65 -0
  302. package/docs/start/framework/actions.md +175 -0
  303. package/docs/start/framework/data-loading.md +201 -0
  304. package/docs/start/framework/deploying.md +96 -0
  305. package/docs/start/framework/index.md +4 -0
  306. package/docs/start/framework/installation.md +42 -0
  307. package/docs/start/framework/navigating.md +182 -0
  308. package/docs/start/framework/pending-ui.md +142 -0
  309. package/docs/start/framework/rendering.md +59 -0
  310. package/docs/start/framework/route-module.md +527 -0
  311. package/docs/start/framework/routing.md +362 -0
  312. package/docs/start/framework/testing.md +133 -0
  313. package/docs/start/index.md +4 -0
  314. package/docs/start/modes.md +201 -0
  315. package/docs/upgrading/component-routes.md +363 -0
  316. package/docs/upgrading/future.md +31 -0
  317. package/docs/upgrading/index.md +4 -0
  318. package/docs/upgrading/remix.md +403 -0
  319. package/docs/upgrading/router-provider.md +442 -0
  320. package/docs/upgrading/v6.md +379 -0
  321. package/package.json +44 -87
  322. package/dist/development/browser-3AnU12UI.d.mts +0 -318
  323. package/dist/development/browser-BOdXz9dK.d.ts +0 -318
  324. package/dist/development/chunk-4N6VE7H7.mjs +0 -11528
  325. package/dist/development/chunk-4YRVXM2U.js +0 -188
  326. package/dist/development/chunk-66UKHEGQ.js +0 -1362
  327. package/dist/development/chunk-D6LUOGOQ.js +0 -10229
  328. package/dist/development/chunk-RJYABSBD.mjs +0 -2585
  329. package/dist/development/context-ByvtofY2.d.mts +0 -1771
  330. package/dist/development/data-BVUf681J.d.mts +0 -1732
  331. package/dist/development/data-BqZ2x964.d.ts +0 -1732
  332. package/dist/development/dom-export.d.mts +0 -172
  333. package/dist/development/dom-export.mjs +0 -1008
  334. package/dist/development/index-react-server-client-BS5F89FR.d.ts +0 -3655
  335. package/dist/development/index-react-server-client-DY04-103.d.mts +0 -2600
  336. package/dist/development/index-react-server-client.d.mts +0 -4
  337. package/dist/development/index-react-server-client.mjs +0 -59
  338. package/dist/development/index-react-server.d.mts +0 -2703
  339. package/dist/development/index-react-server.mjs +0 -3780
  340. package/dist/development/index.d.mts +0 -1472
  341. package/dist/development/index.mjs +0 -277
  342. package/dist/development/instrumentation-cRWWLfsU.d.ts +0 -715
  343. package/dist/development/lib/types/internal.d.mts +0 -184
  344. package/dist/development/lib/types/internal.mjs +0 -10
  345. package/dist/development/register-Df8okEea.d.mts +0 -30
  346. package/dist/production/browser-3AnU12UI.d.mts +0 -318
  347. package/dist/production/browser-BOdXz9dK.d.ts +0 -318
  348. package/dist/production/chunk-6S4627ZB.mjs +0 -2585
  349. package/dist/production/chunk-HUBUW7R3.js +0 -10229
  350. package/dist/production/chunk-JAKZPQZC.mjs +0 -11528
  351. package/dist/production/chunk-PNZCCTKT.js +0 -1362
  352. package/dist/production/chunk-Y6IFXO7V.js +0 -188
  353. package/dist/production/context-ByvtofY2.d.mts +0 -1771
  354. package/dist/production/data-BVUf681J.d.mts +0 -1732
  355. package/dist/production/data-BqZ2x964.d.ts +0 -1732
  356. package/dist/production/dom-export.d.mts +0 -172
  357. package/dist/production/dom-export.mjs +0 -1008
  358. package/dist/production/index-react-server-client-BS5F89FR.d.ts +0 -3655
  359. package/dist/production/index-react-server-client-DY04-103.d.mts +0 -2600
  360. package/dist/production/index-react-server-client.d.mts +0 -4
  361. package/dist/production/index-react-server-client.mjs +0 -59
  362. package/dist/production/index-react-server.d.mts +0 -2703
  363. package/dist/production/index-react-server.mjs +0 -3780
  364. package/dist/production/index.d.mts +0 -1472
  365. package/dist/production/index.mjs +0 -277
  366. package/dist/production/instrumentation-cRWWLfsU.d.ts +0 -715
  367. package/dist/production/lib/types/internal.d.mts +0 -184
  368. package/dist/production/lib/types/internal.mjs +0 -10
  369. package/dist/production/register-Df8okEea.d.mts +0 -30
@@ -0,0 +1,524 @@
1
+ ---
2
+ title: State Management
3
+ ---
4
+
5
+ # State Management
6
+
7
+ [MODES: framework, data]
8
+
9
+ <br/>
10
+ <br/>
11
+
12
+ State management in React typically involves maintaining a synchronized cache of server data on the client side. However, when using React Router as your framework, most of the traditional caching solutions become redundant because of how it inherently handles data synchronization.
13
+
14
+ ## Understanding State Management in React
15
+
16
+ In a typical React context, when we refer to "state management", we're primarily discussing how we synchronize server state with the client. A more apt term could be "cache management" because the server is the source of truth and the client state is mostly functioning as a cache.
17
+
18
+ Popular caching solutions in React include:
19
+
20
+ - **[Redux][redux]:** A predictable state container for JavaScript apps.
21
+ - **[TanStack Query][tanstack_query]:** Hooks for fetching, caching, and updating asynchronous data in React.
22
+ - **[Apollo][apollo]:** A comprehensive state management library for JavaScript that integrates with GraphQL.
23
+
24
+ In certain scenarios, using these libraries may be warranted. However, with React Router's unique server-focused approach, their utility becomes less prevalent. In fact, most React Router applications forgo them entirely.
25
+
26
+ ## How React Router Simplifies State
27
+
28
+ React Router seamlessly bridges the gap between the backend and frontend via mechanisms like loaders, actions, and forms with automatic synchronization through revalidation. This offers developers the ability to directly use server state within components without managing a cache, the network communication, or data revalidation, making most client-side caching redundant.
29
+
30
+ Here's why using typical React state patterns might be an anti-pattern in React Router:
31
+
32
+ 1. **Network-related State:** If your React state is managing anything related to the network—such as data from loaders, pending form submissions, or navigational states—it's likely that you're managing state that React Router already manages:
33
+ - **[`useNavigation`][use_navigation]**: This hook gives you access to `navigation.state`, `navigation.formData`, `navigation.location`, etc.
34
+ - **[`useFetcher`][use_fetcher]**: This facilitates interaction with `fetcher.state`, `fetcher.formData`, `fetcher.data` etc.
35
+ - **[`loaderData`][loader_data]**: Access the data for a route.
36
+ - **[`actionData`][action_data]**: Access the data from the latest action.
37
+
38
+ 2. **Storing Data in React Router:** A lot of data that developers might be tempted to store in React state has a more natural home in React Router, such as:
39
+ - **URL Search Params:** Parameters within the URL that hold state.
40
+ - **[Cookies][cookies]:** Small pieces of data stored on the user's device.
41
+ - **[Server Sessions][sessions]:** Server-managed user sessions.
42
+ - **Server Caches:** Cached data on the server side for quicker retrieval.
43
+
44
+ 3. **Performance Considerations:** At times, client state is leveraged to avoid redundant data fetching. With React Router, you can use the [`Cache-Control`][cache_control_header] headers within `loader`s, allowing you to tap into the browser's native cache. However, this approach has its limitations and should be used judiciously. It's usually more beneficial to optimize backend queries or implement a server cache. This is because such changes benefit all users and do away with the need for individual browser caches.
45
+
46
+ As a developer transitioning to React Router, it's essential to recognize and embrace its inherent efficiencies rather than applying traditional React patterns. React Router offers a streamlined solution to state management leading to less code, fresh data, and no state synchronization bugs.
47
+
48
+ ## Examples
49
+
50
+ ### Network Related State
51
+
52
+ For examples on using React Router's internal state to manage network related state, refer to [Pending UI][pending_ui].
53
+
54
+ ### URL Search Params
55
+
56
+ Consider a UI that lets the user customize between list view or detail view. Your instinct might be to reach for React state:
57
+
58
+ ```tsx bad lines=[2,6,9]
59
+ export function List() {
60
+ const [view, setView] = useState("list");
61
+ return (
62
+ <div>
63
+ <div>
64
+ <button onClick={() => setView("list")}>
65
+ View as List
66
+ </button>
67
+ <button onClick={() => setView("details")}>
68
+ View with Details
69
+ </button>
70
+ </div>
71
+ {view === "list" ? <ListView /> : <DetailView />}
72
+ </div>
73
+ );
74
+ }
75
+ ```
76
+
77
+ Now consider you want the URL to update when the user changes the view. Note the state synchronization:
78
+
79
+ ```tsx bad lines=[7,16,24]
80
+ import { useNavigate, useSearchParams } from "react-router";
81
+
82
+ export function List() {
83
+ const navigate = useNavigate();
84
+ const [searchParams] = useSearchParams();
85
+ const [view, setView] = useState(
86
+ searchParams.get("view") || "list",
87
+ );
88
+
89
+ return (
90
+ <div>
91
+ <div>
92
+ <button
93
+ onClick={() => {
94
+ setView("list");
95
+ navigate(`?view=list`);
96
+ }}
97
+ >
98
+ View as List
99
+ </button>
100
+ <button
101
+ onClick={() => {
102
+ setView("details");
103
+ navigate(`?view=details`);
104
+ }}
105
+ >
106
+ View with Details
107
+ </button>
108
+ </div>
109
+ {view === "list" ? <ListView /> : <DetailView />}
110
+ </div>
111
+ );
112
+ }
113
+ ```
114
+
115
+ Instead of synchronizing state, you can simply read and set the state in the URL directly with boring old HTML forms:
116
+
117
+ ```tsx good lines=[5,9-16]
118
+ import { Form, useSearchParams } from "react-router";
119
+
120
+ export function List() {
121
+ const [searchParams] = useSearchParams();
122
+ const view = searchParams.get("view") || "list";
123
+
124
+ return (
125
+ <div>
126
+ <Form>
127
+ <button name="view" value="list">
128
+ View as List
129
+ </button>
130
+ <button name="view" value="details">
131
+ View with Details
132
+ </button>
133
+ </Form>
134
+ {view === "list" ? <ListView /> : <DetailView />}
135
+ </div>
136
+ );
137
+ }
138
+ ```
139
+
140
+ ### Persistent UI State
141
+
142
+ Consider a UI that toggles a sidebar's visibility. We have three ways to handle the state:
143
+
144
+ 1. React state
145
+ 2. Browser local storage
146
+ 3. Cookies
147
+
148
+ In this discussion, we'll break down the trade-offs associated with each method.
149
+
150
+ #### React State
151
+
152
+ React state provides a simple solution for temporary state storage.
153
+
154
+ **Pros**:
155
+
156
+ - **Simple**: Easy to implement and understand.
157
+ - **Encapsulated**: State is scoped to the component.
158
+
159
+ **Cons**:
160
+
161
+ - **Transient**: Doesn't survive page refreshes, returning to the page later, or unmounting and remounting the component.
162
+
163
+ **Implementation**:
164
+
165
+ ```tsx
166
+ function Sidebar() {
167
+ const [isOpen, setIsOpen] = useState(false);
168
+ return (
169
+ <div>
170
+ <button onClick={() => setIsOpen((open) => !open)}>
171
+ {isOpen ? "Close" : "Open"}
172
+ </button>
173
+ <aside hidden={!isOpen}>
174
+ <Outlet />
175
+ </aside>
176
+ </div>
177
+ );
178
+ }
179
+ ```
180
+
181
+ #### Local Storage
182
+
183
+ To persist state beyond the component lifecycle, browser local storage is a step-up. See our doc on [Client Data][client_data] for more advanced examples.
184
+
185
+ **Pros**:
186
+
187
+ - **Persistent**: Maintains state across page refreshes and component mounts/unmounts.
188
+ - **Encapsulated**: State is scoped to the component.
189
+
190
+ **Cons**:
191
+
192
+ - **Requires Synchronization**: React components must sync up with local storage to initialize and save the current state.
193
+ - **Server Rendering Limitation**: The [`window`][window_global] and [`localStorage`][local_storage_global] objects are not accessible during server-side rendering, so state must be initialized in the browser with an effect.
194
+ - **UI Flickering**: On initial page loads, the state in local storage may not match what was rendered by the server and the UI will flicker when JavaScript loads.
195
+
196
+ **Implementation**:
197
+
198
+ ```tsx
199
+ function Sidebar() {
200
+ const [isOpen, setIsOpen] = useState(false);
201
+
202
+ // synchronize initially
203
+ useLayoutEffect(() => {
204
+ const isOpen = window.localStorage.getItem("sidebar");
205
+ setIsOpen(isOpen);
206
+ }, []);
207
+
208
+ // synchronize on change
209
+ useEffect(() => {
210
+ window.localStorage.setItem("sidebar", isOpen);
211
+ }, [isOpen]);
212
+
213
+ return (
214
+ <div>
215
+ <button onClick={() => setIsOpen((open) => !open)}>
216
+ {isOpen ? "Close" : "Open"}
217
+ </button>
218
+ <aside hidden={!isOpen}>
219
+ <Outlet />
220
+ </aside>
221
+ </div>
222
+ );
223
+ }
224
+ ```
225
+
226
+ In this approach, state must be initialized within an effect. This is crucial to avoid complications during server-side rendering. Directly initializing the React state from `localStorage` will cause errors since `window.localStorage` is unavailable during server rendering.
227
+
228
+ ```tsx bad lines=[4]
229
+ function Sidebar() {
230
+ const [isOpen, setIsOpen] = useState(
231
+ // error: window is not defined
232
+ window.localStorage.getItem("sidebar"),
233
+ );
234
+
235
+ // ...
236
+ }
237
+ ```
238
+
239
+ By initializing the state within an effect, there's potential for a mismatch between the server-rendered state and the state stored in local storage. This discrepancy will lead to brief UI flickering shortly after the page renders and should be avoided.
240
+
241
+ #### Cookies
242
+
243
+ Cookies offer a comprehensive solution for this use case. However, this method introduces added preliminary setup before making the state accessible within the component.
244
+
245
+ **Pros**:
246
+
247
+ - **Server Rendering**: State is available on the server for rendering and even for server actions.
248
+ - **Single Source of Truth**: Eliminates state synchronization hassles.
249
+ - **Persistence**: Maintains state across page loads and component mounts/unmounts. State can even persist across devices if you switch to a database-backed session.
250
+ - **Progressive Enhancement**: Functions even before JavaScript loads.
251
+
252
+ **Cons**:
253
+
254
+ - **Boilerplate**: Requires more code because of the network.
255
+ - **Exposed**: The state is not encapsulated to a single component, other parts of the app must be aware of the cookie.
256
+
257
+ **Implementation**:
258
+
259
+ First we'll need to create a cookie object:
260
+
261
+ ```tsx
262
+ import { createCookie } from "react-router";
263
+ export const prefs = createCookie("prefs");
264
+ ```
265
+
266
+ Next we set up the server action and loader to read and write the cookie:
267
+
268
+ ```tsx filename=app/routes/sidebar.tsx
269
+ import { data, Outlet } from "react-router";
270
+ import type { Route } from "./+types/sidebar";
271
+
272
+ import { prefs } from "./prefs-cookie";
273
+
274
+ // read the state from the cookie
275
+ export async function loader({
276
+ request,
277
+ }: Route.LoaderArgs) {
278
+ const cookieHeader = request.headers.get("Cookie");
279
+ const cookie = (await prefs.parse(cookieHeader)) || {};
280
+ return data({ sidebarIsOpen: cookie.sidebarIsOpen });
281
+ }
282
+
283
+ // write the state to the cookie
284
+ export async function action({
285
+ request,
286
+ }: Route.ActionArgs) {
287
+ const cookieHeader = request.headers.get("Cookie");
288
+ const cookie = (await prefs.parse(cookieHeader)) || {};
289
+ const formData = await request.formData();
290
+
291
+ const isOpen = formData.get("sidebar") === "open";
292
+ cookie.sidebarIsOpen = isOpen;
293
+
294
+ return data(isOpen, {
295
+ headers: {
296
+ "Set-Cookie": await prefs.serialize(cookie),
297
+ },
298
+ });
299
+ }
300
+ ```
301
+
302
+ After the server code is set up, we can use the cookie state in our UI:
303
+
304
+ ```tsx
305
+ function Sidebar({ loaderData }: Route.ComponentProps) {
306
+ const fetcher = useFetcher();
307
+ let { sidebarIsOpen } = loaderData;
308
+
309
+ // use optimistic UI to immediately change the UI state
310
+ if (fetcher.formData?.has("sidebar")) {
311
+ sidebarIsOpen =
312
+ fetcher.formData.get("sidebar") === "open";
313
+ }
314
+
315
+ return (
316
+ <div>
317
+ <fetcher.Form method="post">
318
+ <button
319
+ name="sidebar"
320
+ value={sidebarIsOpen ? "closed" : "open"}
321
+ >
322
+ {sidebarIsOpen ? "Close" : "Open"}
323
+ </button>
324
+ </fetcher.Form>
325
+ <aside hidden={!sidebarIsOpen}>
326
+ <Outlet />
327
+ </aside>
328
+ </div>
329
+ );
330
+ }
331
+ ```
332
+
333
+ While this is certainly more code that touches more of the application to account for the network requests and responses, the UX is greatly improved. Additionally, state comes from a single source of truth without any state synchronization required.
334
+
335
+ In summary, each of the discussed methods offers a unique set of benefits and challenges:
336
+
337
+ - **React state**: Offers simple but transient state management.
338
+ - **Local Storage**: Provides persistence but with synchronization requirements and UI flickering.
339
+ - **Cookies**: Delivers robust, persistent state management at the cost of added boilerplate.
340
+
341
+ None of these are wrong, but if you want to persist the state across visits, cookies offer the best user experience.
342
+
343
+ ### Form Validation and Action Data
344
+
345
+ Client-side validation can augment the user experience, but similar enhancements can be achieved by leaning more towards server-side processing and letting it handle the complexities.
346
+
347
+ The following example illustrates the inherent complexities of managing network state, coordinating state from the server, and implementing validation redundantly on both the client and server sides. It's just for illustration, so forgive any obvious bugs or problems you find.
348
+
349
+ ```tsx bad lines=[2,11,27,38,63]
350
+ export function Signup() {
351
+ // A multitude of React State declarations
352
+ const [isSubmitting, setIsSubmitting] = useState(false);
353
+
354
+ const [userName, setUserName] = useState("");
355
+ const [userNameError, setUserNameError] = useState(null);
356
+
357
+ const [password, setPassword] = useState(null);
358
+ const [passwordError, setPasswordError] = useState("");
359
+
360
+ // Replicating server-side logic in the client
361
+ function validateForm() {
362
+ setUserNameError(null);
363
+ setPasswordError(null);
364
+ const errors = validateSignupForm(userName, password);
365
+ if (errors) {
366
+ if (errors.userName) {
367
+ setUserNameError(errors.userName);
368
+ }
369
+ if (errors.password) {
370
+ setPasswordError(errors.password);
371
+ }
372
+ }
373
+ return Boolean(errors);
374
+ }
375
+
376
+ // Manual network interaction handling
377
+ async function handleSubmit() {
378
+ if (validateForm()) {
379
+ setSubmitting(true);
380
+ const res = await postJSON("/api/signup", {
381
+ userName,
382
+ password,
383
+ });
384
+ const json = await res.json();
385
+ setIsSubmitting(false);
386
+
387
+ // Server state synchronization to the client
388
+ if (json.errors) {
389
+ if (json.errors.userName) {
390
+ setUserNameError(json.errors.userName);
391
+ }
392
+ if (json.errors.password) {
393
+ setPasswordError(json.errors.password);
394
+ }
395
+ }
396
+ }
397
+ }
398
+
399
+ return (
400
+ <form
401
+ onSubmit={(event) => {
402
+ event.preventDefault();
403
+ handleSubmit();
404
+ }}
405
+ >
406
+ <p>
407
+ <input
408
+ type="text"
409
+ name="username"
410
+ value={userName}
411
+ onChange={() => {
412
+ // Synchronizing form state for the fetch
413
+ setUserName(event.target.value);
414
+ }}
415
+ />
416
+ {userNameError ? <i>{userNameError}</i> : null}
417
+ </p>
418
+
419
+ <p>
420
+ <input
421
+ type="password"
422
+ name="password"
423
+ onChange={(event) => {
424
+ // Synchronizing form state for the fetch
425
+ setPassword(event.target.value);
426
+ }}
427
+ />
428
+ {passwordError ? <i>{passwordError}</i> : null}
429
+ </p>
430
+
431
+ <button disabled={isSubmitting} type="submit">
432
+ Sign Up
433
+ </button>
434
+
435
+ {isSubmitting ? <BusyIndicator /> : null}
436
+ </form>
437
+ );
438
+ }
439
+ ```
440
+
441
+ The backend endpoint, `/api/signup`, also performs validation and sends error feedback. Note that some essential validation, like detecting duplicate usernames, can only be done server-side using information the client doesn't have access to.
442
+
443
+ ```tsx bad
444
+ export async function signupHandler(request: Request) {
445
+ const errors = await validateSignupRequest(request);
446
+ if (errors) {
447
+ return { ok: false, errors: errors };
448
+ }
449
+ await signupUser(request);
450
+ return { ok: true, errors: null };
451
+ }
452
+ ```
453
+
454
+ Now, let's contrast this with a React Router-based implementation. The action remains consistent, but the component is vastly simplified due to the direct utilization of server state via `actionData`, and leveraging the network state that React Router inherently manages.
455
+
456
+ ```tsx filename=app/routes/signup.tsx good lines=[20-22]
457
+ import { useNavigation } from "react-router";
458
+ import type { Route } from "./+types/signup";
459
+
460
+ export async function action({
461
+ request,
462
+ }: ActionFunctionArgs) {
463
+ const errors = await validateSignupRequest(request);
464
+ if (errors) {
465
+ return { ok: false, errors: errors };
466
+ }
467
+ await signupUser(request);
468
+ return { ok: true, errors: null };
469
+ }
470
+
471
+ export function Signup({
472
+ actionData,
473
+ }: Route.ComponentProps) {
474
+ const navigation = useNavigation();
475
+
476
+ const userNameError = actionData?.errors?.userName;
477
+ const passwordError = actionData?.errors?.password;
478
+ const isSubmitting = navigation.formAction === "/signup";
479
+
480
+ return (
481
+ <Form method="post">
482
+ <p>
483
+ <input type="text" name="username" />
484
+ {userNameError ? <i>{userNameError}</i> : null}
485
+ </p>
486
+
487
+ <p>
488
+ <input type="password" name="password" />
489
+ {passwordError ? <i>{passwordError}</i> : null}
490
+ </p>
491
+
492
+ <button disabled={isSubmitting} type="submit">
493
+ Sign Up
494
+ </button>
495
+
496
+ {isSubmitting ? <BusyIndicator /> : null}
497
+ </Form>
498
+ );
499
+ }
500
+ ```
501
+
502
+ The extensive state management from our previous example is distilled into just three code lines. We eliminate the necessity for React state, change event listeners, submit handlers, and state management libraries for such network interactions.
503
+
504
+ Direct access to the server state is made possible through `actionData`, and network state through `useNavigation` (or `useFetcher`).
505
+
506
+ As bonus party trick, the form is functional even before JavaScript loads (see [Progressive Enhancement][progressive_enhancement]). Instead of React Router managing the network operations, the default browser behaviors step in.
507
+
508
+ If you ever find yourself entangled in managing and synchronizing state for network operations, React Router likely offers a more elegant solution.
509
+
510
+ [redux]: https://redux.js.org/
511
+ [tanstack_query]: https://tanstack.com/query/latest
512
+ [apollo]: https://www.apollographql.com/
513
+ [use_navigation]: https://api.reactrouter.com/v7/functions/react-router.useNavigation
514
+ [use_fetcher]: https://api.reactrouter.com/v7/functions/react-router.useFetcher
515
+ [loader_data]: ../start/framework/data-loading
516
+ [action_data]: ../start/framework/actions
517
+ [cookies]: ./sessions-and-cookies#cookies
518
+ [sessions]: ./sessions-and-cookies#sessions
519
+ [cache_control_header]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
520
+ [pending_ui]: ../start/framework/pending-ui
521
+ [client_data]: ../how-to/client-data
522
+ [window_global]: https://developer.mozilla.org/en-US/docs/Web/API/Window/window
523
+ [local_storage_global]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
524
+ [progressive_enhancement]: ./progressive-enhancement
@@ -0,0 +1,87 @@
1
+ ---
2
+ title: Styling
3
+ ---
4
+
5
+ # Styling
6
+
7
+ [MODES: framework]
8
+
9
+ <br/>
10
+ <br/>
11
+
12
+ Framework mode uses the React Router Vite plugin, so the styling story is mostly just Vite's styling story.
13
+
14
+ React Router does not have a separate CSS pipeline for Framework mode. In practice, there are three patterns that matter:
15
+
16
+ 1. Import CSS as a side effect
17
+ 2. Use the route module `links` export
18
+ 3. Render a stylesheet `<link>` directly
19
+
20
+ ## Side-Effect CSS Imports
21
+
22
+ Because Framework mode uses Vite, you can import CSS files as side effects:
23
+
24
+ ```tsx filename=app/root.tsx
25
+ import "./app.css";
26
+ ```
27
+
28
+ ```tsx filename=app/routes/dashboard.tsx
29
+ import "./dashboard.css";
30
+ ```
31
+
32
+ This is often the simplest option. Global styles can be imported in `root.tsx`, and route or component styles can be imported next to the module that uses them.
33
+
34
+ ## `links` Export
35
+
36
+ React Router also supports adding stylesheets through the route module `links` export.
37
+
38
+ This is useful when you want a stylesheet URL from Vite and need React Router to render a real `<link rel="stylesheet">` tag for the route:
39
+
40
+ ```tsx filename=app/routes/dashboard.tsx
41
+ import dashboardHref from "./dashboard.css?url";
42
+
43
+ export function links() {
44
+ return [{ rel: "stylesheet", href: dashboardHref }];
45
+ }
46
+ ```
47
+
48
+ The `links` export feeds the [`<Links />`][links-component] component in your root route. This is the React Router-specific styling API in Framework mode. For more on route module exports, see [Route Module][route-module].
49
+
50
+ ## Direct `<link>` Rendering
51
+
52
+ If you're using React 19, you can also render a stylesheet `<link>` directly in your route component:
53
+
54
+ ```tsx filename=app/routes/dashboard.tsx
55
+ import dashboardHref from "./dashboard.css?url";
56
+
57
+ export default function Dashboard() {
58
+ return (
59
+ <>
60
+ <link
61
+ rel="stylesheet"
62
+ href={dashboardHref}
63
+ precedence="default"
64
+ />
65
+ <h1>Dashboard</h1>
66
+ </>
67
+ );
68
+ }
69
+ ```
70
+
71
+ This uses React's built-in [`<link>`][react-link] support, which hoists the stylesheet into the document `<head>`. That gives you another way to colocate stylesheet tags with the route that needs them.
72
+
73
+ ## Everything Else
74
+
75
+ For CSS Modules, Tailwind, PostCSS, Sass, Vanilla Extract, and other styling tools, use the normal Vite setup for those tools.
76
+
77
+ See:
78
+
79
+ - [Vite CSS Features][vite-css]
80
+ - [Vite Static Asset Handling][vite-assets]
81
+ - [`<Links />`][links-component]
82
+
83
+ [links-component]: ../api/components/Links
84
+ [react-link]: https://react.dev/reference/react-dom/components/link
85
+ [route-module]: ../start/framework/route-module
86
+ [vite-assets]: https://vite.dev/guide/assets.html
87
+ [vite-css]: https://vite.dev/guide/features.html#css
@@ -0,0 +1,82 @@
1
+ ---
2
+ title: Type Safety
3
+ ---
4
+
5
+ # Type Safety
6
+
7
+ [MODES: framework]
8
+
9
+ <br/>
10
+ <br/>
11
+
12
+ If you haven't done so already, check out our guide for [setting up type safety][route-module-type-safety] in a new project.
13
+
14
+ React Router generates types for each route in your app to provide type safety for the route module exports.
15
+
16
+ For example, let's say you have a `products/:id` route configured:
17
+
18
+ ```ts filename=app/routes.ts
19
+ import {
20
+ type RouteConfig,
21
+ route,
22
+ } from "@react-router/dev/routes";
23
+
24
+ export default [
25
+ route("products/:id", "./routes/product.tsx"),
26
+ ] satisfies RouteConfig;
27
+ ```
28
+
29
+ You can import route-specific types like so:
30
+
31
+ ```tsx filename=app/routes/product.tsx
32
+ import type { Route } from "./+types/product";
33
+ // types generated for this route 👆
34
+
35
+ export function loader({ params }: Route.LoaderArgs) {
36
+ // 👆 { id: string }
37
+ return { planet: `world #${params.id}` };
38
+ }
39
+
40
+ export default function Component({
41
+ loaderData, // 👈 { planet: string }
42
+ }: Route.ComponentProps) {
43
+ return <h1>Hello, {loaderData.planet}!</h1>;
44
+ }
45
+ ```
46
+
47
+ ## How it works
48
+
49
+ React Router's type generation executes your route config (`app/routes.ts` by default) to determine the routes for your app.
50
+ It then generates a `+types/<route file>.d.ts` for each route within a special `.react-router/types/` directory.
51
+ With [`rootDirs` configured][route-module-type-safety], TypeScript can import these generated files as if they were right next to their corresponding route modules.
52
+
53
+ For a deeper dive into some of the design decisions, check out our [type inference decision doc](https://github.com/remix-run/react-router/blob/dev/decisions/0012-type-inference.md).
54
+
55
+ [route-module-type-safety]: ../how-to/route-module-type-safety
56
+
57
+ ## `typegen` command
58
+
59
+ You can manually generate types with the `typegen` command:
60
+
61
+ ```sh
62
+ react-router typegen
63
+ ```
64
+
65
+ The following types are generated for each route:
66
+
67
+ - `LoaderArgs`
68
+ - `ClientLoaderArgs`
69
+ - `ActionArgs`
70
+ - `ClientActionArgs`
71
+ - `HydrateFallbackProps`
72
+ - `ComponentProps` (for the `default` export)
73
+ - `ErrorBoundaryProps`
74
+
75
+ ### --watch
76
+
77
+ If you run `react-router dev` — or if your custom server calls `vite.createServer` — then React Router's Vite plugin is already generating up-to-date types for you.
78
+ But if you really need to run type generation on its own, you can also use `--watch` to automatically regenerate types as files change:
79
+
80
+ ```sh
81
+ react-router typegen --watch
82
+ ```