From d0694b3c4a5a4c44e0c205aae155d9f39ed2a494 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Thu, 23 Feb 2023 08:36:14 -0500 Subject: [PATCH 1/4] fix: treat absolute/same-origin/different-basename values as external --- .changeset/big-olives-doubt.md | 5 ++ .../__tests__/link-click-test.tsx | 73 ++++++++++++++++++- packages/react-router-dom/index.tsx | 8 +- 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 .changeset/big-olives-doubt.md diff --git a/.changeset/big-olives-doubt.md b/.changeset/big-olives-doubt.md new file mode 100644 index 0000000000..006cb6ce52 --- /dev/null +++ b/.changeset/big-olives-doubt.md @@ -0,0 +1,5 @@ +--- +"react-router-dom": patch +--- + +Treat absolute/same-origin/different-basename values as external diff --git a/packages/react-router-dom/__tests__/link-click-test.tsx b/packages/react-router-dom/__tests__/link-click-test.tsx index d3a8facd4c..e754b025dd 100644 --- a/packages/react-router-dom/__tests__/link-click-test.tsx +++ b/packages/react-router-dom/__tests__/link-click-test.tsx @@ -138,7 +138,6 @@ describe("A click", () => {

Home

{ handlerCalled = true; @@ -171,6 +170,78 @@ describe("A click", () => { }); }); + describe("when a same-origin/different-basename absolute URL is specified", () => { + it.only("does not prevent default", () => { + function Home() { + return ( +
+

Home

+ About +
+ ); + } + + act(() => { + ReactDOM.createRoot(node).render( + + + } /> + + + ); + }); + + let anchor = node.querySelector("a"); + expect(anchor).not.toBeNull(); + + let event: MouseEvent; + act(() => { + event = click(anchor); + }); + + expect(event.defaultPrevented).toBe(false); + }); + + it("calls provided listener", () => { + let handlerCalled; + let defaultPrevented; + + function Home() { + return ( +
+

Home

+ { + handlerCalled = true; + defaultPrevented = e.defaultPrevented; + }} + > + About + +
+ ); + } + + act(() => { + ReactDOM.createRoot(node).render( + + + } /> + + + ); + }); + + act(() => { + click(node.querySelector("a")); + }); + + expect(handlerCalled).toBe(true); + expect(defaultPrevented).toBe(false); + }); + }); + describe("when reloadDocument is specified", () => { it("does not prevent default", () => { function Home() { diff --git a/packages/react-router-dom/index.tsx b/packages/react-router-dom/index.tsx index 1c24998adc..cbaef2ee54 100644 --- a/packages/react-router-dom/index.tsx +++ b/packages/react-router-dom/index.tsx @@ -42,6 +42,7 @@ import { createHashHistory, UNSAFE_invariant as invariant, joinPaths, + stripBasename, ErrorResponse, } from "@remix-run/router"; @@ -420,6 +421,8 @@ export const Link = React.forwardRef( }, ref ) { + let { basename } = React.useContext(NavigationContext); + // Rendered into for absolute URLs let absoluteHref; let isExternal = false; @@ -434,7 +437,10 @@ export const Link = React.forwardRef( let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to); - if (targetUrl.origin === currentUrl.origin) { + let isSameBasename = + stripBasename(targetUrl.pathname, basename) != null; + + if (targetUrl.origin === currentUrl.origin && isSameBasename) { // Strip the protocol/origin for same-origin absolute URLs to = targetUrl.pathname + targetUrl.search + targetUrl.hash; } else { From a6f96127e72de883979c8cdf987b18b27c91e36f Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Thu, 23 Feb 2023 08:41:25 -0500 Subject: [PATCH 2/4] Remove .only --- packages/react-router-dom/__tests__/link-click-test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-router-dom/__tests__/link-click-test.tsx b/packages/react-router-dom/__tests__/link-click-test.tsx index e754b025dd..29e878ce76 100644 --- a/packages/react-router-dom/__tests__/link-click-test.tsx +++ b/packages/react-router-dom/__tests__/link-click-test.tsx @@ -171,7 +171,7 @@ describe("A click", () => { }); describe("when a same-origin/different-basename absolute URL is specified", () => { - it.only("does not prevent default", () => { + it("does not prevent default", () => { function Home() { return (
From 3f987eb82b2ea51878be45fbcd7ee632e4838d4b Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Thu, 23 Feb 2023 08:47:51 -0500 Subject: [PATCH 3/4] Support same-basename client-side navigations --- .../__tests__/link-push-test.tsx | 43 +++++++++++++++++++ packages/react-router-dom/index.tsx | 10 ++--- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/packages/react-router-dom/__tests__/link-push-test.tsx b/packages/react-router-dom/__tests__/link-push-test.tsx index 305f1f1009..07b3263429 100644 --- a/packages/react-router-dom/__tests__/link-push-test.tsx +++ b/packages/react-router-dom/__tests__/link-push-test.tsx @@ -283,4 +283,47 @@ describe("Link push and replace", () => { `); }); }); + + describe("to an absolute same-origin/same-basename URL, when it is clicked", () => { + it("performs a push", () => { + function Home() { + return ( +
+

Home

+ About +
+ ); + } + + let renderer: TestRenderer.ReactTestRenderer; + TestRenderer.act(() => { + renderer = TestRenderer.create( + + + } /> + } /> + + + ); + }); + + let anchor = renderer.root.findByType("a"); + + TestRenderer.act(() => { + anchor.props.onClick( + new MouseEvent("click", { + view: window, + bubbles: true, + cancelable: true, + }) + ); + }); + + expect(renderer.toJSON()).toMatchInlineSnapshot(` +

+ PUSH +

+ `); + }); + }); }); diff --git a/packages/react-router-dom/index.tsx b/packages/react-router-dom/index.tsx index cbaef2ee54..c4678efbb5 100644 --- a/packages/react-router-dom/index.tsx +++ b/packages/react-router-dom/index.tsx @@ -428,6 +428,7 @@ export const Link = React.forwardRef( let isExternal = false; if (typeof to === "string" && ABSOLUTE_URL_REGEX.test(to)) { + debugger; // Render the absolute href server- and client-side absoluteHref = to; @@ -437,12 +438,11 @@ export const Link = React.forwardRef( let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to); - let isSameBasename = - stripBasename(targetUrl.pathname, basename) != null; + let path = stripBasename(targetUrl.pathname, basename); - if (targetUrl.origin === currentUrl.origin && isSameBasename) { - // Strip the protocol/origin for same-origin absolute URLs - to = targetUrl.pathname + targetUrl.search + targetUrl.hash; + if (targetUrl.origin === currentUrl.origin && path != null) { + // Strip the protocol/origin/basename for same-origin absolute URLs + to = path + targetUrl.search + targetUrl.hash; } else { isExternal = true; } From 9f5fdb03fd0cece1b5da5032ce59a409e61b3686 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Thu, 23 Feb 2023 08:50:44 -0500 Subject: [PATCH 4/4] Bump bundle --- package.json | 2 +- packages/react-router-dom/index.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 446186dc2d..7ededba1ec 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ "none": "15 kB" }, "packages/react-router-dom/dist/react-router-dom.production.min.js": { - "none": "11.5 kB" + "none": "11.6 kB" }, "packages/react-router-dom/dist/umd/react-router-dom.production.min.js": { "none": "17.5 kB" diff --git a/packages/react-router-dom/index.tsx b/packages/react-router-dom/index.tsx index c4678efbb5..e7884bc18b 100644 --- a/packages/react-router-dom/index.tsx +++ b/packages/react-router-dom/index.tsx @@ -428,7 +428,6 @@ export const Link = React.forwardRef( let isExternal = false; if (typeof to === "string" && ABSOLUTE_URL_REGEX.test(to)) { - debugger; // Render the absolute href server- and client-side absoluteHref = to;