From 5843d381a60b195d0590d556dc322090f92e2185 Mon Sep 17 00:00:00 2001 From: Syed Sohail Hussain <162160794+syedsohailhussain1@users.noreply.github.com> Date: Tue, 18 Aug 2026 15:59:38 -0400 Subject: [PATCH 1/6] refactor(router): use definite assignment assertions in createDeferred (#15396) * refactor(router): use definite assignment assertions in createDeferred * Add syedsohailhussain1 to contributors list --- contributors.yml | 1 + packages/react-router/lib/router/router.ts | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/contributors.yml b/contributors.yml index 759fd10a60..5a923bae9a 100644 --- a/contributors.yml +++ b/contributors.yml @@ -522,3 +522,4 @@ - zeroqs - zheng-chuang - zxTomw +- syedsohailhussain1 diff --git a/packages/react-router/lib/router/router.ts b/packages/react-router/lib/router/router.ts index 97d346fa04..db266eab0e 100644 --- a/packages/react-router/lib/router/router.ts +++ b/packages/react-router/lib/router/router.ts @@ -7680,11 +7680,11 @@ function persistAppliedTransitions( } function createDeferred() { - let resolve: (val?: any) => Promise; - let reject: (error?: Error) => Promise; + let resolve!: (val?: T) => Promise; + let reject!: (error?: Error) => Promise; let promise = new Promise((res, rej) => { - resolve = async (val: T) => { - res(val); + resolve = async (val?: T) => { + res(val as T); try { await promise; } catch {} @@ -7698,9 +7698,7 @@ function createDeferred() { }); return { promise, - //@ts-ignore resolve, - //@ts-ignore reject, }; } From 4fc28de3d49d4ca2480d55a8d0824989b1b445d5 Mon Sep 17 00:00:00 2001 From: Remix Run Bot Date: Tue, 18 Aug 2026 20:00:17 +0000 Subject: [PATCH 2/6] chore: format --- contributors.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributors.yml b/contributors.yml index 5a923bae9a..a5f2d0c791 100644 --- a/contributors.yml +++ b/contributors.yml @@ -446,6 +446,7 @@ - sunnyraindy - sushichan044 - swalker326 +- syedsohailhussain1 - szhsin - tanayv - thecode00 @@ -522,4 +523,3 @@ - zeroqs - zheng-chuang - zxTomw -- syedsohailhussain1 From 3d00d479e4bfcd3825cc5accba08d8aeb3794c49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Aug 2026 16:02:35 -0400 Subject: [PATCH 3/6] chore(deps): bump pnpm/action-setup from 6.0.9 to 6.0.10 (#15381) Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 6.0.9 to 6.0.10. - [Release notes](https://github.com/pnpm/action-setup/releases) - [Commits](https://github.com/pnpm/action-setup/compare/v6.0.9...v6.0.10) --- updated-dependencies: - dependency-name: pnpm/action-setup dependency-version: 6.0.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deduplicate-lock-file.yml | 2 +- .github/workflows/docs.yml | 2 +- .github/workflows/format.yml | 2 +- .github/workflows/pr-actions.yml | 2 +- .github/workflows/pr-checks.yml | 2 +- .github/workflows/preview.yml | 2 +- .github/workflows/release-comments-manual.yml | 2 +- .github/workflows/release.yml | 8 ++++---- .github/workflows/test-integration-run.yml | 2 +- .github/workflows/test-unit.yml | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/deduplicate-lock-file.yml b/.github/workflows/deduplicate-lock-file.yml index a50d429581..468a82f1fc 100644 --- a/.github/workflows/deduplicate-lock-file.yml +++ b/.github/workflows/deduplicate-lock-file.yml @@ -23,7 +23,7 @@ jobs: token: ${{ secrets.FORMAT_PAT }} - name: Setup pnpm - uses: pnpm/action-setup@v6.0.9 + uses: pnpm/action-setup@v6.0.10 - name: Setup node uses: actions/setup-node@v6 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 57da20019f..824633f6e0 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -31,7 +31,7 @@ jobs: ref: ${{ github.event.inputs.branch }} - name: Setup pnpm - uses: pnpm/action-setup@v6.0.9 + uses: pnpm/action-setup@v6.0.10 - name: Setup node uses: actions/setup-node@v6 diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index e52f37203f..1a47e0cc2d 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -22,7 +22,7 @@ jobs: token: ${{ secrets.FORMAT_PAT }} - name: Setup pnpm - uses: pnpm/action-setup@v6.0.9 + uses: pnpm/action-setup@v6.0.10 - name: Setup node uses: actions/setup-node@v6 diff --git a/.github/workflows/pr-actions.yml b/.github/workflows/pr-actions.yml index 9e47361b15..c88a3d7967 100644 --- a/.github/workflows/pr-actions.yml +++ b/.github/workflows/pr-actions.yml @@ -28,7 +28,7 @@ jobs: uses: actions/checkout@v7 - name: Setup pnpm - uses: pnpm/action-setup@v6.0.9 + uses: pnpm/action-setup@v6.0.10 - name: Setup node uses: actions/setup-node@v6 diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 744fed1870..9454108868 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -62,7 +62,7 @@ jobs: - name: Setup pnpm if: steps.changed-files.outputs.mode == 'run' - uses: pnpm/action-setup@v6.0.9 + uses: pnpm/action-setup@v6.0.10 - name: Setup node if: steps.changed-files.outputs.mode == 'run' diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 1f69a45502..24f26ecf21 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -56,7 +56,7 @@ jobs: ref: ${{ inputs.baseBranch }} - name: Install pnpm - uses: pnpm/action-setup@v6.0.9 + uses: pnpm/action-setup@v6.0.10 - name: Install Node.js uses: actions/setup-node@v6 diff --git a/.github/workflows/release-comments-manual.yml b/.github/workflows/release-comments-manual.yml index a9412bce39..62d8db5228 100644 --- a/.github/workflows/release-comments-manual.yml +++ b/.github/workflows/release-comments-manual.yml @@ -25,7 +25,7 @@ jobs: fetch-depth: 0 - name: Setup pnpm - uses: pnpm/action-setup@v6.0.9 + uses: pnpm/action-setup@v6.0.10 - name: Setup node uses: actions/setup-node@v6 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2f543de2c7..fa731c548a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -87,7 +87,7 @@ jobs: token: ${{ secrets.FORMAT_PAT }} - name: Install pnpm - uses: pnpm/action-setup@v6.0.9 + uses: pnpm/action-setup@v6.0.10 - name: Install Node.js uses: actions/setup-node@v6 @@ -116,7 +116,7 @@ jobs: uses: actions/checkout@v7 - name: Setup pnpm - uses: pnpm/action-setup@v6.0.9 + uses: pnpm/action-setup@v6.0.10 - name: Setup node uses: actions/setup-node@v6 @@ -151,7 +151,7 @@ jobs: fetch-depth: 0 - name: Setup pnpm - uses: pnpm/action-setup@v6.0.9 + uses: pnpm/action-setup@v6.0.10 - name: Setup node uses: actions/setup-node@v6 @@ -184,7 +184,7 @@ jobs: fetch-depth: 0 - name: Setup pnpm - uses: pnpm/action-setup@v6.0.9 + uses: pnpm/action-setup@v6.0.10 - name: Setup node uses: actions/setup-node@v6 diff --git a/.github/workflows/test-integration-run.yml b/.github/workflows/test-integration-run.yml index 91fab70456..68dc80fcff 100644 --- a/.github/workflows/test-integration-run.yml +++ b/.github/workflows/test-integration-run.yml @@ -30,7 +30,7 @@ jobs: uses: actions/checkout@v7 - name: Setup pnpm - uses: pnpm/action-setup@v6.0.9 + uses: pnpm/action-setup@v6.0.10 - name: Setup node ${{ inputs.node_version }} uses: actions/setup-node@v6 diff --git a/.github/workflows/test-unit.yml b/.github/workflows/test-unit.yml index 6c8b8e7ebd..71c6a2b557 100644 --- a/.github/workflows/test-unit.yml +++ b/.github/workflows/test-unit.yml @@ -37,7 +37,7 @@ jobs: uses: actions/checkout@v7 - name: Setup pnpm - uses: pnpm/action-setup@v6.0.9 + uses: pnpm/action-setup@v6.0.10 - name: Setup node uses: actions/setup-node@v6 From 2b6bf7a4ffaef2263d0a0e0f9f9d7df533f23908 Mon Sep 17 00:00:00 2001 From: Kobi Hikri Date: Tue, 18 Aug 2026 23:12:42 +0300 Subject: [PATCH 4/6] ci: read the PR head ref from env instead of interpolating it into the shell (#15352) --- .github/workflows/test-integration.yml | 3 ++- contributors.yml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index 0e5a82e96d..4ef1c19e6a 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -56,6 +56,7 @@ jobs: id: suites env: GH_TOKEN: ${{ github.token }} + PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} # If `gh pr diff` exits with a non-zero code, it might be because the PR # has >300 files, or it could be for any number of unknown reasons. If # that happens take the conservative route and run the larger `dev` suite. @@ -63,7 +64,7 @@ jobs: if [ "${{ github.event_name }}" = "push" ]; then echo "Selected integration suite: full (push to main)" echo "type=full" >> "$GITHUB_OUTPUT" - elif [ "${{ github.event.pull_request.head.ref }}" = "v8" ]; then + elif [ "$PR_HEAD_REF" = "v8" ]; then echo "Selected integration suite: dev (v8 PR)" echo "type=dev" >> "$GITHUB_OUTPUT" elif [ "${{ github.event.pull_request.draft }}" = "true" ]; then diff --git a/contributors.yml b/contributors.yml index a5f2d0c791..a399fdfb45 100644 --- a/contributors.yml +++ b/contributors.yml @@ -256,6 +256,7 @@ - kklem0 - kno-raziel - knownasilya +- kobihikri - koojaa - KostiantynPopovych - KubasuIvanSakwa From 91b191183d07d7659d7850b29401baf16de05521 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Tue, 18 Aug 2026 16:13:23 -0400 Subject: [PATCH 5/6] Remove v8 specific branch check --- .github/workflows/test-integration.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index 4ef1c19e6a..5773e25b87 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -56,7 +56,6 @@ jobs: id: suites env: GH_TOKEN: ${{ github.token }} - PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} # If `gh pr diff` exits with a non-zero code, it might be because the PR # has >300 files, or it could be for any number of unknown reasons. If # that happens take the conservative route and run the larger `dev` suite. @@ -64,9 +63,6 @@ jobs: if [ "${{ github.event_name }}" = "push" ]; then echo "Selected integration suite: full (push to main)" echo "type=full" >> "$GITHUB_OUTPUT" - elif [ "$PR_HEAD_REF" = "v8" ]; then - echo "Selected integration suite: dev (v8 PR)" - echo "type=dev" >> "$GITHUB_OUTPUT" elif [ "${{ github.event.pull_request.draft }}" = "true" ]; then echo "Selected integration suite: base (draft PR)" echo "type=base" >> "$GITHUB_OUTPUT" From 5e9814084f4a59df8e194c240feb97b558984b89 Mon Sep 17 00:00:00 2001 From: dfedoryshchev <64079946+dfedoryshchev@users.noreply.github.com> Date: Tue, 18 Aug 2026 21:26:26 +0100 Subject: [PATCH 6/6] fix: honor the relative option in useSubmit and fetcher.submit (#15400) * fix: honor the relative option in useSubmit and fetcher.submit * Updates --------- Co-authored-by: Matt Brophy --- .../.changes/patch.submit-relative-option.md | 1 + .../dom/data-browser-router-test.tsx | 94 +++++++++++++++++++ packages/react-router/lib/dom/lib.tsx | 2 + 3 files changed, 97 insertions(+) create mode 100644 packages/react-router/.changes/patch.submit-relative-option.md diff --git a/packages/react-router/.changes/patch.submit-relative-option.md b/packages/react-router/.changes/patch.submit-relative-option.md new file mode 100644 index 0000000000..5daed14b08 --- /dev/null +++ b/packages/react-router/.changes/patch.submit-relative-option.md @@ -0,0 +1 @@ +Properly respect the `relative` option in `useSubmit`/`fetcher.submit` when resolivng the `action` path diff --git a/packages/react-router/__tests__/dom/data-browser-router-test.tsx b/packages/react-router/__tests__/dom/data-browser-router-test.tsx index f8c33542c2..00124d62ee 100644 --- a/packages/react-router/__tests__/dom/data-browser-router-test.tsx +++ b/packages/react-router/__tests__/dom/data-browser-router-test.tsx @@ -4132,6 +4132,100 @@ function testDomRouter( }); }); + describe('submit() with relative="path"', () => { + it("submits relative to the URL for navigations", async () => { + let router = createTestRouter( + [ + { + path: "inbox", + action: () => "INDEX", + children: [ + { + path: "messages", + action: () => "MESSAGES", + Component() { + let actionData = useActionData(); + return

{actionData}

; + }, + }, + { + path: "messages/:id", + Component() { + let submit = useSubmit(); + return ( + + ); + }, + }, + ], + }, + ], + { window: getWindow("/inbox/messages/1") }, + ); + render(); + + fireEvent.click(screen.getByText("Submit")); + await waitFor(() => screen.getByText("MESSAGES")); + expect(router.state.location.pathname).toBe("/inbox/messages"); + }); + + it("submits relative to the URL for fetchers", async () => { + let router = createTestRouter( + [ + { + path: "inbox", + action: () => "INDEX", + children: [ + { + path: "messages", + action: () => "MESSAGES", + }, + { + path: "messages/:id", + Component() { + let fetcher = useFetcher(); + return ( + <> + + {fetcher.data ?

{fetcher.data}

: null} + + ); + }, + }, + ], + }, + ], + { window: getWindow("/inbox/messages/1") }, + ); + render(); + + fireEvent.click(screen.getByText("Submit")); + await waitFor(() => screen.getByText("MESSAGES")); + }); + }); + describe("useSubmit/Form FormData", () => { it("gathers form data on
submissions", async () => { let actionSpy = jest.fn(); diff --git a/packages/react-router/lib/dom/lib.tsx b/packages/react-router/lib/dom/lib.tsx index 94ad1aae67..f779abea62 100644 --- a/packages/react-router/lib/dom/lib.tsx +++ b/packages/react-router/lib/dom/lib.tsx @@ -2603,6 +2603,7 @@ export function useSubmit(): SubmitFunction { await routerFetch(key, currentRouteId, options.action || action, { defaultShouldRevalidate: options.defaultShouldRevalidate, preventScrollReset: options.preventScrollReset, + relative: options.relative, formData, body, formMethod: options.method || (method as HTMLFormMethod), @@ -2613,6 +2614,7 @@ export function useSubmit(): SubmitFunction { await routerNavigate(options.action || action, { defaultShouldRevalidate: options.defaultShouldRevalidate, preventScrollReset: options.preventScrollReset, + relative: options.relative, formData, body, formMethod: options.method || (method as HTMLFormMethod),