diff --git a/.changeset/pre.json b/.changeset/pre.json index 5292247897..370fee1430 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -36,5 +36,10 @@ "@playground/split-route-modules-spa": "0.0.0", "@playground/vite-plugin-cloudflare": "0.0.0" }, - "changesets": [] + "changesets": [ + "breezy-planes-roll", + "green-pens-push", + "quick-eels-join", + "six-lobsters-think" + ] } diff --git a/packages/create-react-router/CHANGELOG.md b/packages/create-react-router/CHANGELOG.md index da45cd74b2..b568ce6a01 100644 --- a/packages/create-react-router/CHANGELOG.md +++ b/packages/create-react-router/CHANGELOG.md @@ -1,5 +1,7 @@ # `create-react-router` +## 7.9.4-pre.0 + ## 7.9.3 ## 7.9.2 diff --git a/packages/create-react-router/package.json b/packages/create-react-router/package.json index f0eab96b1a..12b2b43891 100644 --- a/packages/create-react-router/package.json +++ b/packages/create-react-router/package.json @@ -1,6 +1,6 @@ { "name": "create-react-router", - "version": "7.9.3", + "version": "7.9.4-pre.0", "description": "Create a new React Router app", "homepage": "https://reactrouter.com", "bugs": { diff --git a/packages/react-router-architect/CHANGELOG.md b/packages/react-router-architect/CHANGELOG.md index 5ec74a1162..6b490f824c 100644 --- a/packages/react-router-architect/CHANGELOG.md +++ b/packages/react-router-architect/CHANGELOG.md @@ -1,5 +1,13 @@ # `@react-router/architect` +## 7.9.4-pre.0 + +### Patch Changes + +- Updated dependencies: + - `react-router@7.9.4-pre.0` + - `@react-router/node@7.9.4-pre.0` + ## 7.9.3 ### Patch Changes diff --git a/packages/react-router-architect/package.json b/packages/react-router-architect/package.json index 9b63583c6f..9338237309 100644 --- a/packages/react-router-architect/package.json +++ b/packages/react-router-architect/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/architect", - "version": "7.9.3", + "version": "7.9.4-pre.0", "description": "Architect server request handler for React Router", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router-cloudflare/CHANGELOG.md b/packages/react-router-cloudflare/CHANGELOG.md index d74b9aa8d9..514ce4ed59 100644 --- a/packages/react-router-cloudflare/CHANGELOG.md +++ b/packages/react-router-cloudflare/CHANGELOG.md @@ -1,5 +1,12 @@ # `@react-router/cloudflare` +## 7.9.4-pre.0 + +### Patch Changes + +- Updated dependencies: + - `react-router@7.9.4-pre.0` + ## 7.9.3 ### Patch Changes diff --git a/packages/react-router-cloudflare/package.json b/packages/react-router-cloudflare/package.json index 249f43f0f8..af600ec3fe 100644 --- a/packages/react-router-cloudflare/package.json +++ b/packages/react-router-cloudflare/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/cloudflare", - "version": "7.9.3", + "version": "7.9.4-pre.0", "description": "Cloudflare platform abstractions for React Router", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router-dev/CHANGELOG.md b/packages/react-router-dev/CHANGELOG.md index 2d0aa8e6df..9639e668e0 100644 --- a/packages/react-router-dev/CHANGELOG.md +++ b/packages/react-router-dev/CHANGELOG.md @@ -1,5 +1,115 @@ # `@react-router/dev` +## 7.9.4-pre.0 + +### Patch Changes + +- Update `valibot` dependency to `^1.1.0` ([#14379](https://github.com/remix-run/react-router/pull/14379)) +- New (unstable) `useRoute` hook for accessing data from specific routes ([#14407](https://github.com/remix-run/react-router/pull/14407)) + + 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.` + + ```tsx + // app/routes/admin.tsx + import { Outlet } from "react-router"; + + export const loader = () => ({ message: "Hello, loader!" }); + + export const action = () => ({ count: 1 }); + + export default function Component() { + return ( +
+ {/* ... */} + + {/* ... */} +
+ ); + } + ``` + + You might even want to create a reusable widget that all of the routes nested under `admin` could use: + + ```tsx + import { unstable_useRoute as useRoute } from "react-router"; + + export function AdminWidget() { + // How to get `message` and `count` from `admin` route? + } + ``` + + In framework mode, `useRoute` knows all your app's routes and gives you TS errors when invalid route IDs are passed in: + + ```tsx + export function AdminWidget() { + const admin = useRoute("routes/dmin"); + // ^^^^^^^^^^^ + } + ``` + + `useRoute` returns `undefined` if the route is not part of the current page: + + ```tsx + export function AdminWidget() { + const admin = useRoute("routes/admin"); + if (!admin) { + throw new Error(`AdminWidget used outside of "routes/admin"`); + } + } + ``` + + Note: the `root` route is the exception since it is guaranteed to be part of the current page. + As a result, `useRoute` never returns `undefined` for `root`. + + `loaderData` and `actionData` are marked as optional since they could be accessed before the `action` is triggered or after the `loader` threw an error: + + ```tsx + export function AdminWidget() { + const admin = useRoute("routes/admin"); + if (!admin) { + throw new Error(`AdminWidget used outside of "routes/admin"`); + } + const { loaderData, actionData } = admin; + console.log(loaderData); + // ^? { message: string } | undefined + console.log(actionData); + // ^? { count: number } | undefined + } + ``` + + If instead of a specific route, you wanted access to the _current_ route's `loaderData` and `actionData`, you can call `useRoute` without arguments: + + ```tsx + export function AdminWidget() { + const currentRoute = useRoute(); + currentRoute.loaderData; + currentRoute.actionData; + } + ``` + + This usage is equivalent to calling `useLoaderData` and `useActionData`, but consolidates all route data access into one hook: `useRoute`. + + Note: when calling `useRoute()` (without a route ID), TS has no way to know which route is the current route. + As a result, `loaderData` and `actionData` are typed as `unknown`. + 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`: + + ```tsx + export function AdminWidget({ + message, + count, + }: { + message: string; + count: number; + }) { + /* ... */ + } + ``` + +- Updated dependencies: + - `react-router@7.9.4-pre.0` + - `@react-router/node@7.9.4-pre.0` + - `@react-router/serve@7.9.4-pre.0` + ## 7.9.3 ### Patch Changes diff --git a/packages/react-router-dev/package.json b/packages/react-router-dev/package.json index fc0d72d1e2..9d558e4d0c 100644 --- a/packages/react-router-dev/package.json +++ b/packages/react-router-dev/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/dev", - "version": "7.9.3", + "version": "7.9.4-pre.0", "description": "Dev tools and CLI for React Router", "homepage": "https://reactrouter.com", "bugs": { diff --git a/packages/react-router-dom/CHANGELOG.md b/packages/react-router-dom/CHANGELOG.md index 75c2ecb0ef..fb278e5db9 100644 --- a/packages/react-router-dom/CHANGELOG.md +++ b/packages/react-router-dom/CHANGELOG.md @@ -1,5 +1,12 @@ # react-router-dom +## 7.9.4-pre.0 + +### Patch Changes + +- Updated dependencies: + - `react-router@7.9.4-pre.0` + ## 7.9.3 ### Patch Changes diff --git a/packages/react-router-dom/package.json b/packages/react-router-dom/package.json index 715770624e..07882a79b7 100644 --- a/packages/react-router-dom/package.json +++ b/packages/react-router-dom/package.json @@ -1,6 +1,6 @@ { "name": "react-router-dom", - "version": "7.9.3", + "version": "7.9.4-pre.0", "description": "Declarative routing for React web applications", "keywords": [ "react", diff --git a/packages/react-router-express/CHANGELOG.md b/packages/react-router-express/CHANGELOG.md index d3e49f9170..2abc575995 100644 --- a/packages/react-router-express/CHANGELOG.md +++ b/packages/react-router-express/CHANGELOG.md @@ -1,5 +1,13 @@ # `@react-router/express` +## 7.9.4-pre.0 + +### Patch Changes + +- Updated dependencies: + - `react-router@7.9.4-pre.0` + - `@react-router/node@7.9.4-pre.0` + ## 7.9.3 ### Patch Changes diff --git a/packages/react-router-express/package.json b/packages/react-router-express/package.json index 18f5bf6a13..69ccc57335 100644 --- a/packages/react-router-express/package.json +++ b/packages/react-router-express/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/express", - "version": "7.9.3", + "version": "7.9.4-pre.0", "description": "Express server request handler for React Router", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router-fs-routes/CHANGELOG.md b/packages/react-router-fs-routes/CHANGELOG.md index 0153883a9c..3bb3c8ae43 100644 --- a/packages/react-router-fs-routes/CHANGELOG.md +++ b/packages/react-router-fs-routes/CHANGELOG.md @@ -1,5 +1,12 @@ # `@react-router/fs-routes` +## 7.9.4-pre.0 + +### Patch Changes + +- Updated dependencies: + - `@react-router/dev@7.9.4-pre.0` + ## 7.9.3 ### Patch Changes diff --git a/packages/react-router-fs-routes/package.json b/packages/react-router-fs-routes/package.json index d7728fd930..1b8d3d223e 100644 --- a/packages/react-router-fs-routes/package.json +++ b/packages/react-router-fs-routes/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/fs-routes", - "version": "7.9.3", + "version": "7.9.4-pre.0", "description": "File system routing conventions for React Router, for use within routes.ts", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router-node/CHANGELOG.md b/packages/react-router-node/CHANGELOG.md index 8955ab93d2..5fe4f76bfa 100644 --- a/packages/react-router-node/CHANGELOG.md +++ b/packages/react-router-node/CHANGELOG.md @@ -1,5 +1,13 @@ # `@react-router/node` +## 7.9.4-pre.0 + +### Patch Changes + +- Validate format of incoming session ids ([#14426](https://github.com/remix-run/react-router/pull/14426)) +- Updated dependencies: + - `react-router@7.9.4-pre.0` + ## 7.9.3 ### Patch Changes diff --git a/packages/react-router-node/package.json b/packages/react-router-node/package.json index be542771c3..91ea0eeaef 100644 --- a/packages/react-router-node/package.json +++ b/packages/react-router-node/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/node", - "version": "7.9.3", + "version": "7.9.4-pre.0", "description": "Node.js platform abstractions for React Router", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router-remix-routes-option-adapter/CHANGELOG.md b/packages/react-router-remix-routes-option-adapter/CHANGELOG.md index 7d95d12953..63d3bfa64a 100644 --- a/packages/react-router-remix-routes-option-adapter/CHANGELOG.md +++ b/packages/react-router-remix-routes-option-adapter/CHANGELOG.md @@ -1,5 +1,12 @@ # `@react-router/remix-config-routes-adapter` +## 7.9.4-pre.0 + +### Patch Changes + +- Updated dependencies: + - `@react-router/dev@7.9.4-pre.0` + ## 7.9.3 ### Patch Changes diff --git a/packages/react-router-remix-routes-option-adapter/package.json b/packages/react-router-remix-routes-option-adapter/package.json index 691b5353ab..17994e4ec1 100644 --- a/packages/react-router-remix-routes-option-adapter/package.json +++ b/packages/react-router-remix-routes-option-adapter/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/remix-routes-option-adapter", - "version": "7.9.3", + "version": "7.9.4-pre.0", "description": "Adapter for Remix's \"routes\" config option, for use within routes.ts", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router-serve/CHANGELOG.md b/packages/react-router-serve/CHANGELOG.md index cb2c8edc65..0ef42b1322 100644 --- a/packages/react-router-serve/CHANGELOG.md +++ b/packages/react-router-serve/CHANGELOG.md @@ -1,5 +1,14 @@ # `@react-router/serve` +## 7.9.4-pre.0 + +### Patch Changes + +- Updated dependencies: + - `react-router@7.9.4-pre.0` + - `@react-router/node@7.9.4-pre.0` + - `@react-router/express@7.9.4-pre.0` + ## 7.9.3 ### Patch Changes diff --git a/packages/react-router-serve/package.json b/packages/react-router-serve/package.json index 4d42b286a5..121fea9074 100644 --- a/packages/react-router-serve/package.json +++ b/packages/react-router-serve/package.json @@ -1,6 +1,6 @@ { "name": "@react-router/serve", - "version": "7.9.3", + "version": "7.9.4-pre.0", "description": "Production application server for React Router", "bugs": { "url": "https://github.com/remix-run/react-router/issues" diff --git a/packages/react-router/CHANGELOG.md b/packages/react-router/CHANGELOG.md index 2f0d19ed90..5d713cc6fe 100644 --- a/packages/react-router/CHANGELOG.md +++ b/packages/react-router/CHANGELOG.md @@ -1,5 +1,110 @@ # `react-router` +## 7.9.4-pre.0 + +### Patch Changes + +- handle external redirects in from server actions ([#14400](https://github.com/remix-run/react-router/pull/14400)) +- New (unstable) `useRoute` hook for accessing data from specific routes ([#14407](https://github.com/remix-run/react-router/pull/14407)) + + 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.` + + ```tsx + // app/routes/admin.tsx + import { Outlet } from "react-router"; + + export const loader = () => ({ message: "Hello, loader!" }); + + export const action = () => ({ count: 1 }); + + export default function Component() { + return ( +
+ {/* ... */} + + {/* ... */} +
+ ); + } + ``` + + You might even want to create a reusable widget that all of the routes nested under `admin` could use: + + ```tsx + import { unstable_useRoute as useRoute } from "react-router"; + + export function AdminWidget() { + // How to get `message` and `count` from `admin` route? + } + ``` + + In framework mode, `useRoute` knows all your app's routes and gives you TS errors when invalid route IDs are passed in: + + ```tsx + export function AdminWidget() { + const admin = useRoute("routes/dmin"); + // ^^^^^^^^^^^ + } + ``` + + `useRoute` returns `undefined` if the route is not part of the current page: + + ```tsx + export function AdminWidget() { + const admin = useRoute("routes/admin"); + if (!admin) { + throw new Error(`AdminWidget used outside of "routes/admin"`); + } + } + ``` + + Note: the `root` route is the exception since it is guaranteed to be part of the current page. + As a result, `useRoute` never returns `undefined` for `root`. + + `loaderData` and `actionData` are marked as optional since they could be accessed before the `action` is triggered or after the `loader` threw an error: + + ```tsx + export function AdminWidget() { + const admin = useRoute("routes/admin"); + if (!admin) { + throw new Error(`AdminWidget used outside of "routes/admin"`); + } + const { loaderData, actionData } = admin; + console.log(loaderData); + // ^? { message: string } | undefined + console.log(actionData); + // ^? { count: number } | undefined + } + ``` + + If instead of a specific route, you wanted access to the _current_ route's `loaderData` and `actionData`, you can call `useRoute` without arguments: + + ```tsx + export function AdminWidget() { + const currentRoute = useRoute(); + currentRoute.loaderData; + currentRoute.actionData; + } + ``` + + This usage is equivalent to calling `useLoaderData` and `useActionData`, but consolidates all route data access into one hook: `useRoute`. + + Note: when calling `useRoute()` (without a route ID), TS has no way to know which route is the current route. + As a result, `loaderData` and `actionData` are typed as `unknown`. + 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`: + + ```tsx + export function AdminWidget({ + message, + count, + }: { + message: string; + count: number; + }) { + /* ... */ + } + ``` + ## 7.9.3 ### Patch Changes diff --git a/packages/react-router/package.json b/packages/react-router/package.json index 563bcad27c..1f1ef9ac12 100644 --- a/packages/react-router/package.json +++ b/packages/react-router/package.json @@ -1,6 +1,6 @@ { "name": "react-router", - "version": "7.9.3", + "version": "7.9.4-pre.0", "description": "Declarative routing for React", "keywords": [ "react",