diff --git a/docs/api.md b/docs/api.md index 2ce434c14a..5834bb6bed 100644 --- a/docs/api.md +++ b/docs/api.md @@ -252,17 +252,17 @@ interface LinkProps "href" > { replace?: boolean; - state?: State; + state?: any; to: To; + reloadDocument?: boolean; } -type State = object | null; type To = Partial | string; ``` -A `` is an element that lets the user navigate to another page by clicking or tapping on it. In `react-router-dom`, a `` renders an accessible `` element with a real `href` that points to the resource it's linking to. This means that things like right-clicking a `` work as you'd expect. +A `` is an element that lets the user navigate to another page by clicking or tapping on it. In `react-router-dom`, a `` renders an accessible `` element with a real `href` that points to the resource it's linking to. This means that things like right-clicking a `` work as you'd expect. You can use `` to skip client side routing and let the browser handle the transition normally (as if it were an ``). ```tsx import * as React from "react"; diff --git a/packages/react-router-dom/__tests__/link-click-test.tsx b/packages/react-router-dom/__tests__/link-click-test.tsx index 15bfe7035e..0b4878895d 100644 --- a/packages/react-router-dom/__tests__/link-click-test.tsx +++ b/packages/react-router-dom/__tests__/link-click-test.tsx @@ -3,15 +3,15 @@ import * as ReactDOM from "react-dom"; import { act } from "react-dom/test-utils"; import { MemoryRouter, Routes, Route, Link } from "react-router-dom"; -function click(anchor: HTMLAnchorElement, eventInit?: MouseEventInit): void { - anchor.dispatchEvent( - new MouseEvent("click", { - view: window, - bubbles: true, - cancelable: true, - ...eventInit - }) - ); +function click(anchor: HTMLAnchorElement, eventInit?: MouseEventInit) { + let event = new MouseEvent("click", { + view: window, + bubbles: true, + cancelable: true, + ...eventInit + }); + anchor.dispatchEvent(event); + return event; } describe("A click", () => { @@ -51,15 +51,54 @@ describe("A click", () => { let anchor = node.querySelector("a"); expect(anchor).not.toBeNull(); + let event: MouseEvent; act(() => { - click(anchor); + event = click(anchor); }); + expect(event.defaultPrevented).toBe(true); let h1 = node.querySelector("h1"); expect(h1).not.toBeNull(); expect(h1?.textContent).toEqual("About"); }); + describe("when reloadDocument is specified", () => { + it("does not prevent default", () => { + function Home() { + return ( +
+

Home

+ + About + +
+ ); + } + + act(() => { + ReactDOM.render( + + + } /> + About} /> + + , + node + ); + }); + + let anchor = node.querySelector("a"); + expect(anchor).not.toBeNull(); + + let event: MouseEvent; + act(() => { + event = click(anchor); + }); + + expect(event.defaultPrevented).toBe(false); + }); + }); + describe("when preventDefault is used on the click handler", () => { it("stays on the same page", () => { function Home() { diff --git a/packages/react-router-dom/index.tsx b/packages/react-router-dom/index.tsx index eb74683ea4..eaa8a8ba9e 100644 --- a/packages/react-router-dom/index.tsx +++ b/packages/react-router-dom/index.tsx @@ -200,6 +200,7 @@ function isModifiedEvent(event: React.MouseEvent) { export interface LinkProps extends Omit, "href"> { + reloadDocument?: boolean; replace?: boolean; state?: any; to: To; @@ -210,7 +211,7 @@ export interface LinkProps */ export const Link = React.forwardRef( function LinkWithRef( - { onClick, replace = false, state, target, to, ...rest }, + { onClick, reloadDocument, replace = false, state, target, to, ...rest }, ref ) { let href = useHref(to); @@ -219,7 +220,7 @@ export const Link = React.forwardRef( event: React.MouseEvent ) { if (onClick) onClick(event); - if (!event.defaultPrevented) { + if (!event.defaultPrevented && !reloadDocument) { internalOnClick(event); } }