Skip to content

Commit 5920ded

Browse files
committed
Merge branch 'main' into release-next
2 parents 4e85e98 + 5d66dbd commit 5920ded

File tree

12 files changed

+384
-126
lines changed

12 files changed

+384
-126
lines changed

.github/workflows/release-nightly.yml

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
name: 🌒 Nightly Release
2+
3+
on:
4+
workflow_dispatch:
5+
schedule:
6+
- cron: "0 7 * * *" # every day at 12AM PST
7+
8+
concurrency:
9+
group: ${{ github.workflow }}-${{ github.ref }}
10+
cancel-in-progress: true
11+
12+
env:
13+
CI: true
14+
15+
jobs:
16+
# HEADS UP! this "nightly" job will only ever run on the `main` branch due to
17+
# it being a cron job, and the last commit on main will be what github shows
18+
# as the trigger however in the checkout below we specify the `v7` branch,
19+
# so all the scripts in this job will be ran from that, confusing i know, so
20+
# in some cases we'll need to create multiple PRs when modifying nightly
21+
# release processes
22+
nightly:
23+
name: 🌒 Nightly Release
24+
if: github.repository == 'remix-run/react-router'
25+
runs-on: ubuntu-latest
26+
outputs:
27+
# allows this to be used in the `comment` job below - will be undefined
28+
# if there's no release necessary
29+
NEXT_VERSION: ${{ steps.version.outputs.NEXT_VERSION }}
30+
steps:
31+
- name: ⬇️ Checkout repo
32+
uses: actions/checkout@v4
33+
with:
34+
ref: v7
35+
# checkout using a custom token so that we can push later on
36+
token: ${{ secrets.GITHUB_TOKEN }}
37+
fetch-depth: 0
38+
39+
- name: 📦 Setup pnpm
40+
uses: pnpm/[email protected]
41+
42+
- name: ⎔ Setup node
43+
uses: actions/setup-node@v4
44+
with:
45+
node-version-file: ".nvmrc"
46+
cache: "pnpm"
47+
48+
- name: 📥 Install deps
49+
run: pnpm install --frozen-lockfile
50+
51+
- name: 🕵️ Check for changes
52+
id: version
53+
run: |
54+
SHORT_SHA=$(git rev-parse --short HEAD)
55+
56+
# get latest nightly tag
57+
LATEST_NIGHTLY_TAG=$(git tag -l v0.0.0-nightly-\* --sort=-creatordate | head -n 1)
58+
59+
# check if last commit to v7 starts with the nightly tag we're about
60+
# to create (minus the date)
61+
# if it is, we'll skip the nightly creation
62+
# if not, we'll create a new nightly tag
63+
if [[ ${LATEST_NIGHTLY_TAG} == v0.0.0-nightly-${SHORT_SHA}-* ]]; then
64+
echo "🛑 Latest nightly tag is the same as the latest commit sha, skipping nightly release"
65+
else
66+
# yyyyMMdd format (e.g. 20221207)
67+
DATE=$(date '+%Y%m%d')
68+
# v0.0.0-nightly-<short sha>-<date>
69+
NEXT_VERSION=0.0.0-nightly-${SHORT_SHA}-${DATE}
70+
# set output so it can be used in other jobs
71+
echo "NEXT_VERSION=${NEXT_VERSION}" >> $GITHUB_OUTPUT
72+
fi
73+
74+
- name: ⤴️ Update version
75+
if: steps.version.outputs.NEXT_VERSION
76+
run: |
77+
git config --local user.email "[email protected]"
78+
git config --local user.name "Remix Run Bot"
79+
git checkout -b nightly/${{ steps.version.outputs.NEXT_VERSION }}
80+
pnpm run version ${{steps.version.outputs.NEXT_VERSION}}
81+
git push origin --tags
82+
83+
- name: 🏗 Build
84+
if: steps.version.outputs.NEXT_VERSION
85+
run: pnpm build
86+
87+
- name: 🔐 Setup npm auth
88+
if: steps.version.outputs.NEXT_VERSION
89+
run: |
90+
echo "registry=https://registry.npmjs.org" >> ~/.npmrc
91+
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc
92+
93+
- name: 🚀 Publish
94+
if: steps.version.outputs.NEXT_VERSION
95+
run: pnpm run publish

CHANGELOG.md

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ Date: 2023-10-16
491491

492492
#### View Transitions 🚀
493493

494-
We're excited to release experimental support for the the [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/ViewTransition) in React Router! You can now trigger navigational DOM updates to be wrapped in `document.startViewTransition` to enable CSS animated transitions on SPA navigations in your application.
494+
We're excited to release experimental support for the [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/ViewTransition) in React Router! You can now trigger navigational DOM updates to be wrapped in `document.startViewTransition` to enable CSS animated transitions on SPA navigations in your application.
495495

496496
The simplest approach to enabling a View Transition in your React Router app is via the new [`<Link unstable_viewTransition>`](https://reactrouter.com/components/link#unstable_viewtransition) prop. This will cause the navigation DOM update to be wrapped in `document.startViewTransition` which will enable transitions for the DOM update. Without any additional CSS styles, you'll get a basic cross-fade animation for your page.
497497

@@ -711,6 +711,8 @@ Date: 2023-06-14
711711

712712
`6.13.0` is really a patch release in spirit but comes with a SemVer minor bump since we added a new future flag.
713713

714+
#### v7_startTransition
715+
714716
The **tl;dr;** is that `6.13.0` is the same as [`6.12.0`](https://github.com/remix-run/react-router/releases/tag/react-router%406.12.0) bue we've moved the usage of `React.startTransition` behind an opt-in `future.v7_startTransition` [future flag](https://reactrouter.com/en/main/guides/api-development-strategy) because we found that there are applications in the wild that are currently using `Suspense` in ways that are incompatible with `React.startTransition`.
715717

716718
Therefore, in `6.13.0` the default behavior will no longer leverage `React.startTransition`:
@@ -862,14 +864,16 @@ You can also check out the docs [here](https://reactrouter.com/en/dev/guides/api
862864

863865
### Minor Changes
864866

865-
- The first future flag being introduced is `future.v7_normalizeFormMethod` which will normalize the exposed `useNavigation()/useFetcher()` `formMethod` fields as uppercase HTTP methods to align with the `fetch()` (and some Remix) behavior. ([#10207](https://github.com/remix-run/react-router/pull/10207))
867+
#### future.v7_normalizeFormMethod
868+
869+
The first future flag being introduced is `future.v7_normalizeFormMethod` which will normalize the exposed `useNavigation()/useFetcher()` `formMethod` fields as uppercase HTTP methods to align with the `fetch()` (and some Remix) behavior. ([#10207](https://github.com/remix-run/react-router/pull/10207))
866870

867-
- When `future.v7_normalizeFormMethod` is unspecified or set to `false` (default v6 behavior),
868-
- `useNavigation().formMethod` is lowercase
869-
- `useFetcher().formMethod` is lowercase
870-
- When `future.v7_normalizeFormMethod === true`:
871-
- `useNavigation().formMethod` is UPPERCASE
872-
- `useFetcher().formMethod` is UPPERCASE
871+
- When `future.v7_normalizeFormMethod` is unspecified or set to `false` (default v6 behavior),
872+
- `useNavigation().formMethod` is lowercase
873+
- `useFetcher().formMethod` is lowercase
874+
- When `future.v7_normalizeFormMethod === true`:
875+
- `useNavigation().formMethod` is UPPERCASE
876+
- `useFetcher().formMethod` is UPPERCASE
873877

874878
### Patch Changes
875879

@@ -1046,7 +1050,7 @@ Support absolute URLs in `<Link to>`. If the URL is for the current origin, it w
10461050

10471051
- Fixes 2 separate issues for revalidating fetcher `shouldRevalidate` calls ([#9948](https://github.com/remix-run/react-router/pull/9948))
10481052
- The `shouldRevalidate` function was only being called for _explicit_ revalidation scenarios (after a mutation, manual `useRevalidator` call, or an `X-Remix-Revalidate` header used for cookie setting in Remix). It was not properly being called on _implicit_ revalidation scenarios that also apply to navigation `loader` revalidation, such as a change in search params or clicking a link for the page we're already on. It's now correctly called in those additional scenarios.
1049-
- The parameters being passed were incorrect and inconsistent with one another since the `current*`/`next*` parameters reflected the static `fetcher.load` URL (and thus were identical). Instead, they should have reflected the the navigation that triggered the revalidation (as the `form*` parameters did). These parameters now correctly reflect the triggering navigation.
1053+
- The parameters being passed were incorrect and inconsistent with one another since the `current*`/`next*` parameters reflected the static `fetcher.load` URL (and thus were identical). Instead, they should have reflected the navigation that triggered the revalidation (as the `form*` parameters did). These parameters now correctly reflect the triggering navigation.
10501054
- Fix bug with search params removal via `useSearchParams` ([#9969](https://github.com/remix-run/react-router/pull/9969))
10511055
- Respect `preventScrollReset` on `<fetcher.Form>` ([#9963](https://github.com/remix-run/react-router/pull/9963))
10521056
- Fix navigation for hash routers on manual URL changes ([#9980](https://github.com/remix-run/react-router/pull/9980))

contributors.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
- appden
2323
- arjunyel
2424
- arka1002
25+
- Armanio
2526
- arnassavickas
2627
- aroyan
2728
- ashusnapx
@@ -53,6 +54,7 @@
5354
- christowiz
5455
- codeape2
5556
- coryhouse
57+
- ctnelson1997
5658
- cvbuelow
5759
- damianstasik
5860
- danielberndt
@@ -81,6 +83,9 @@
8183
- frontsideair
8284
- fyzhu
8385
- fz6m
86+
- gaspard
87+
- Geist5000
88+
- gesposito
8489
- gianlucca
8590
- gijo-varghese
8691
- goldins
@@ -192,6 +197,8 @@
192197
- noisypigeon
193198
- Nurai1
194199
- Obi-Dann
200+
- OlegDev1
201+
- omahs
195202
- omar-moquete
196203
- p13i
197204
- parched
@@ -206,6 +213,7 @@
206213
- rimian
207214
- robbtraister
208215
- RobHannay
216+
- robinvdvleuten
209217
- rtmann
210218
- rubeonline
211219
- ryanflorence
@@ -243,6 +251,7 @@
243251
- tlinhart
244252
- tom-sherman
245253
- tomasr8
254+
- tony-sn
246255
- TooTallNate
247256
- triangularcube
248257
- trungpv1601

docs/components/form.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ function ProjectsPage() {
9292
</DataBrowserRouter>;
9393
```
9494

95-
If the the current URL is `"/projects/123"`, the form inside the child
95+
If the current URL is `"/projects/123"`, the form inside the child
9696
route, `ProjectsPage`, will have a default action as you might expect: `"/projects/123"`. In this case, where the route is the deepest matching route, both `<Form>` and plain HTML forms have the same result.
9797

9898
But the form inside of `ProjectsLayout` will point to `"/projects"`, not the full URL. In other words, it points to the matching segment of the URL for the route in which the form is rendered.

docs/guides/api-development-strategy.md

Lines changed: 16 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -5,115 +5,40 @@ new: true
55

66
# API Development Strategy
77

8-
Let's cut to the chase - major version upgrades can be a _pain_. Especially for something as foundational to your application as the framework or router it's built on. For Remix and React Router, we want to do our best to give you the smoothest upgrade experience possible.
8+
React Router is foundational to your application. We want to make sure that upgrading to new major versions is as smooth as possible while still allowing us to adjust and enhance the behavior and API as the React ecosystem advances.
99

10-
<docs-info>This strategy is discussed in more detail in our [Future Flags][future-flags-blog-post] blog post, so give that a read if you want any more info at the end of this doc!</docs-info>
10+
Our strategy and motivations are discussed in more detail in our [Future Flags][future-flags-blog-post] blog post.
1111

12-
## Goals
12+
## Future Flags
1313

14-
Our goals for major Remix and React Router releases are:
14+
When an API changes in a breaking way, it is introduced in a future flag. This allows you to opt-in to one change a time before it becomes the default in the next major version.
1515

16-
- Developers can opt-into SemVer-major features individually _as they are released_ instead of having to wait to adopt them all at once when a new major version hits NPM
17-
- Having opted into features ahead-of-time, developers can upgrade to new major versions in a single short-lived branch/commit (hours, not weeks)
16+
- Without enabling the future flag, nothing changes about your app
17+
- Enabling the flag changes the behavior for that feature
1818

19-
## Implementation
19+
All current future flags are documented in the [Future Flags Guide](../upgrading/future) to help you stay up-to-date.
2020

21-
We plan to do this via what we're calling **Future Flags** that you'll provide when you initialize your [Data Router][picking-a-router]. Think of these as **feature flags for future features**. As we implement new features, we always try to do them in a backwards-compatible way. But when a breaking change is warranted, we don't table that feature up for an _eventual_ v7 release. Instead, we add a **Future Flag** and implement the new feature alongside the current behavior in a v6 minor release. This allows users to start using the feature, providing feedback, and reporting bugs _immediately_.
21+
## Unstable Flags
2222

23-
That way, not only can you adopt features incrementally (and eagerly without a major version bump), we can also work out any kinks incrementally _before_ releasing v7. Eventually we also then add deprecation warnings to the v6 releases to nudge users to the new behavior. Then in v7 we remove the old v6 approach, remove the deprecations, and remove the flag - thus making the flagged behavior the new default in v7. If at the time v6 is released, an application has opted into _all_ future flags and updated their code - then they should just be able to update their dependency to v7, delete the future flags, and be running on v7 in a matter of minutes.
23+
Unstable flags are for features still being designed and developed and made available to our users to help us get it right.
2424

25-
## Unstable vs. V7 Flags
25+
Unstable flags are not recommended for production:
2626

27-
Future flags come in 2 forms:
27+
- they will change without warning and without upgrade paths
28+
- they will have bugs
29+
- they aren't documented
30+
- they may be scrapped completely
2831

29-
**`future.unstable_feature`**
32+
When you opt-in to an unstable flag you are becoming a contributor to the project, rather than a user. We appreciate your help, but please be aware of the new role!
3033

31-
`unstable_` flags allow us to iterate on the API with early adopters as if we're in `v0.x.x` versions, but for a specific feature. This avoids churning the API for all users and arriving at better APIs in the final release. This _does not mean_ that we think the feature is bug-ridden! We _absolutely_ want early adopters to start using these features so we can iterate on (and/or gain confidence in) the API.
32-
33-
**`future.v7_feature`**
34-
35-
`v7_` indicates a breaking change from v6 behavior and implies (1) that the API is considered stable and will not under any more breaking changes and (2) that the API will become the default behavior in v7. A `v7_` flag _does not_ mean the feature is bug-free - no software is! Our recommendation is to upgrade to v7 flags as you have the time, as it will make your v7 upgrade _much_ smoother.
34+
To learn about current unstable flags, keep an eye on the [CHANGELOG](../start/changelog).
3635

3736
### Example New Feature Flow
3837

3938
The decision flow for a new feature looks something like this (note this diagram is in relation to Remix v1/v2 but applies to React Router v6/v7 as well):
4039

4140
![Flowchart of the decision process for how to introduce a new feature][feature-flowchart]
4241

43-
The lifecycle is thus either:
44-
45-
- Non-Breaking + Stable API Feature -> Lands in v6
46-
- Non-Breaking + Unstable API -> `future.unstable_` flag -> Lands in v6
47-
- Breaking + Stable API Feature -> `future.v7_` flag -> Lands in v7
48-
- Breaking + Unstable API -> `future.unstable_` flag -> `future.v7_` flag -> Lands in v7
49-
50-
## Current Future Flags
51-
52-
Here's the current future flags in React Router v6 today.
53-
54-
### `@remix-run/router` Future Flags
55-
56-
These flags are only applicable when using a [Data Router][picking-a-router] and are passed when creating the `router` instance:
57-
58-
```js
59-
const router = createBrowserRouter(routes, {
60-
future: {
61-
v7_normalizeFormMethod: true,
62-
},
63-
});
64-
```
65-
66-
| Flag | Description |
67-
| ------------------------------------------- | --------------------------------------------------------------------- |
68-
| `v7_fetcherPersist` | Delay active fetcher cleanup until they return to an `idle` state |
69-
| `v7_normalizeFormMethod` | Normalize `useNavigation().formMethod` to be an uppercase HTTP Method |
70-
| [`v7_partialHydration`][partialhydration] | Support partial hydration for Server-rendered apps |
71-
| `v7_prependBasename` | Prepend the router basename to navigate/fetch paths |
72-
| [`v7_relativeSplatPath`][relativesplatpath] | Fix buggy relative path resolution in splat routes |
73-
74-
#### `createStaticHandler` Future Flags
75-
76-
These flags are only applicable when [SSR][ssr]-ing a React Router app:
77-
78-
```js
79-
const handler = createStaticHandler(routes, {
80-
future: {
81-
v7_throwAbortReason: true,
82-
},
83-
});
84-
```
85-
86-
| Flag | Description |
87-
| ------------------------------------------- | ----------------------------------------------------------------------- |
88-
| [`v7_relativeSplatPath`][relativesplatpath] | Fix buggy relative path resolution in splat routes |
89-
| [`v7_throwAbortReason`][abortreason] | Throw `request.signal.reason` if a `query`/`queryRoute` call is aborted |
90-
91-
### React Router Future Flags
92-
93-
These flags apply to both Data and non-Data Routers and are passed to the rendered React component:
94-
95-
```jsx
96-
<BrowserRouter future={{ v7_startTransition: true }}>
97-
<Routes>{/*...*/}</Routes>
98-
</BrowserRouter>
99-
```
100-
101-
```jsx
102-
<RouterProvider
103-
router={router}
104-
future={{ v7_startTransition: true }}
105-
/>
106-
```
107-
108-
| Flag | Description |
109-
| -------------------- | --------------------------------------------------------------------------- |
110-
| `v7_startTransition` | Wrap all router state updates in [`React.startTransition`][starttransition] |
111-
11242
[future-flags-blog-post]: https://remix.run/blog/future-flags
11343
[feature-flowchart]: https://remix.run/docs-images/feature-flowchart.png
11444
[picking-a-router]: ../routers/picking-a-router
115-
[starttransition]: https://react.dev/reference/react/startTransition
116-
[partialhydration]: ../routers/create-browser-router#partial-hydration-data
117-
[relativesplatpath]: ../hooks/use-resolved-path#splat-paths
118-
[ssr]: ../guides/ssr
119-
[abortreason]: ../routers/create-static-handler#handlerqueryrequest-opts

docs/hooks/use-navigate.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ function EditContact() {
9393
}
9494
```
9595

96-
Please note that `relative: "path"` only impacts the resolution of a relative path. It does not change the the "starting" location for that relative path resolution. This resolution is always relative to the current location in the Route hierarchy (i.e., the route `useNavigate` is called in).
96+
Please note that `relative: "path"` only impacts the resolution of a relative path. It does not change the "starting" location for that relative path resolution. This resolution is always relative to the current location in the Route hierarchy (i.e., the route `useNavigate` is called in).
9797

9898
If you wish to use path-relative routing against the current URL instead of the route hierarchy, you can do that with the current [`location`][use-location] and the `URL` constructor (note the trailing slash behavior):
9999

0 commit comments

Comments
 (0)