|
1 | 1 | # `@react-router/dev` |
2 | 2 |
|
| 3 | +## 7.9.4-pre.0 |
| 4 | + |
| 5 | +### Patch Changes |
| 6 | + |
| 7 | +- Update `valibot` dependency to `^1.1.0` ([#14379](https://github.com/remix-run/react-router/pull/14379)) |
| 8 | +- New (unstable) `useRoute` hook for accessing data from specific routes ([#14407](https://github.com/remix-run/react-router/pull/14407)) |
| 9 | + |
| 10 | + For example, let's say you have an `admin` route somewhere in your app and you want any child routes of `admin` to all have access to the `loaderData` and `actionData` from `admin.` |
| 11 | + |
| 12 | + ```tsx |
| 13 | + // app/routes/admin.tsx |
| 14 | + import { Outlet } from "react-router"; |
| 15 | + |
| 16 | + export const loader = () => ({ message: "Hello, loader!" }); |
| 17 | + |
| 18 | + export const action = () => ({ count: 1 }); |
| 19 | + |
| 20 | + export default function Component() { |
| 21 | + return ( |
| 22 | + <div> |
| 23 | + {/* ... */} |
| 24 | + <Outlet /> |
| 25 | + {/* ... */} |
| 26 | + </div> |
| 27 | + ); |
| 28 | + } |
| 29 | + ``` |
| 30 | + |
| 31 | + You might even want to create a reusable widget that all of the routes nested under `admin` could use: |
| 32 | + |
| 33 | + ```tsx |
| 34 | + import { unstable_useRoute as useRoute } from "react-router"; |
| 35 | + |
| 36 | + export function AdminWidget() { |
| 37 | + // How to get `message` and `count` from `admin` route? |
| 38 | + } |
| 39 | + ``` |
| 40 | + |
| 41 | + In framework mode, `useRoute` knows all your app's routes and gives you TS errors when invalid route IDs are passed in: |
| 42 | + |
| 43 | + ```tsx |
| 44 | + export function AdminWidget() { |
| 45 | + const admin = useRoute("routes/dmin"); |
| 46 | + // ^^^^^^^^^^^ |
| 47 | + } |
| 48 | + ``` |
| 49 | + |
| 50 | + `useRoute` returns `undefined` if the route is not part of the current page: |
| 51 | + |
| 52 | + ```tsx |
| 53 | + export function AdminWidget() { |
| 54 | + const admin = useRoute("routes/admin"); |
| 55 | + if (!admin) { |
| 56 | + throw new Error(`AdminWidget used outside of "routes/admin"`); |
| 57 | + } |
| 58 | + } |
| 59 | + ``` |
| 60 | + |
| 61 | + Note: the `root` route is the exception since it is guaranteed to be part of the current page. |
| 62 | + As a result, `useRoute` never returns `undefined` for `root`. |
| 63 | + |
| 64 | + `loaderData` and `actionData` are marked as optional since they could be accessed before the `action` is triggered or after the `loader` threw an error: |
| 65 | + |
| 66 | + ```tsx |
| 67 | + export function AdminWidget() { |
| 68 | + const admin = useRoute("routes/admin"); |
| 69 | + if (!admin) { |
| 70 | + throw new Error(`AdminWidget used outside of "routes/admin"`); |
| 71 | + } |
| 72 | + const { loaderData, actionData } = admin; |
| 73 | + console.log(loaderData); |
| 74 | + // ^? { message: string } | undefined |
| 75 | + console.log(actionData); |
| 76 | + // ^? { count: number } | undefined |
| 77 | + } |
| 78 | + ``` |
| 79 | + |
| 80 | + If instead of a specific route, you wanted access to the _current_ route's `loaderData` and `actionData`, you can call `useRoute` without arguments: |
| 81 | + |
| 82 | + ```tsx |
| 83 | + export function AdminWidget() { |
| 84 | + const currentRoute = useRoute(); |
| 85 | + currentRoute.loaderData; |
| 86 | + currentRoute.actionData; |
| 87 | + } |
| 88 | + ``` |
| 89 | + |
| 90 | + This usage is equivalent to calling `useLoaderData` and `useActionData`, but consolidates all route data access into one hook: `useRoute`. |
| 91 | + |
| 92 | + Note: when calling `useRoute()` (without a route ID), TS has no way to know which route is the current route. |
| 93 | + As a result, `loaderData` and `actionData` are typed as `unknown`. |
| 94 | + If you want more type-safety, you can either narrow the type yourself with something like `zod` or you can refactor your app to pass down typed props to your `AdminWidget`: |
| 95 | + |
| 96 | + ```tsx |
| 97 | + export function AdminWidget({ |
| 98 | + message, |
| 99 | + count, |
| 100 | + }: { |
| 101 | + message: string; |
| 102 | + count: number; |
| 103 | + }) { |
| 104 | + /* ... */ |
| 105 | + } |
| 106 | + ``` |
| 107 | + |
| 108 | +- Updated dependencies: |
| 109 | + |
| 110 | + - `@react-router/[email protected]` |
| 111 | + - `@react-router/[email protected]` |
| 112 | + |
3 | 113 | ## 7.9.3 |
4 | 114 |
|
5 | 115 | ### Patch Changes |
|
0 commit comments