Skip to content

Commit b7d0e1c

Browse files
jacob-ebeyryanflorence
authored andcommitted
feat: added reloadDocument to <Link> and <NavLink> (#8283)
* feat: added forceDocument to `<Link>` * renamed to reloadDocument * chore(docs): added docs on reloadDocument * chore(docs): typos Co-authored-by: Ryan Florence <[email protected]>
1 parent 739af00 commit b7d0e1c

File tree

3 files changed

+55
-15
lines changed

3 files changed

+55
-15
lines changed

docs/api.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,17 +252,17 @@ interface LinkProps
252252
"href"
253253
> {
254254
replace?: boolean;
255-
state?: State;
255+
state?: any;
256256
to: To;
257+
reloadDocument?: boolean;
257258
}
258259

259-
type State = object | null;
260260
type To = Partial<Location> | string;
261261
```
262262

263263
</details>
264264

265-
A `<Link>` is an element that lets the user navigate to another page by clicking or tapping on it. In `react-router-dom`, a `<Link>` renders an accessible `<a>` element with a real `href` that points to the resource it's linking to. This means that things like right-clicking a `<Link>` work as you'd expect.
265+
A `<Link>` is an element that lets the user navigate to another page by clicking or tapping on it. In `react-router-dom`, a `<Link>` renders an accessible `<a>` element with a real `href` that points to the resource it's linking to. This means that things like right-clicking a `<Link>` work as you'd expect. You can use `<Link reloadDocument>` to skip client side routing and let the browser handle the transition normally (as if it were an `<a href>`).
266266

267267
```tsx
268268
import * as React from "react";

packages/react-router-dom/__tests__/link-click-test.tsx

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ import * as ReactDOM from "react-dom";
33
import { act } from "react-dom/test-utils";
44
import { MemoryRouter, Routes, Route, Link } from "react-router-dom";
55

6-
function click(anchor: HTMLAnchorElement, eventInit?: MouseEventInit): void {
7-
anchor.dispatchEvent(
8-
new MouseEvent("click", {
9-
view: window,
10-
bubbles: true,
11-
cancelable: true,
12-
...eventInit
13-
})
14-
);
6+
function click(anchor: HTMLAnchorElement, eventInit?: MouseEventInit) {
7+
let event = new MouseEvent("click", {
8+
view: window,
9+
bubbles: true,
10+
cancelable: true,
11+
...eventInit
12+
});
13+
anchor.dispatchEvent(event);
14+
return event;
1515
}
1616

1717
describe("A <Link> click", () => {
@@ -51,15 +51,54 @@ describe("A <Link> click", () => {
5151
let anchor = node.querySelector("a");
5252
expect(anchor).not.toBeNull();
5353

54+
let event: MouseEvent;
5455
act(() => {
55-
click(anchor);
56+
event = click(anchor);
5657
});
5758

59+
expect(event.defaultPrevented).toBe(true);
5860
let h1 = node.querySelector("h1");
5961
expect(h1).not.toBeNull();
6062
expect(h1?.textContent).toEqual("About");
6163
});
6264

65+
describe("when reloadDocument is specified", () => {
66+
it("does not prevent default", () => {
67+
function Home() {
68+
return (
69+
<div>
70+
<h1>Home</h1>
71+
<Link reloadDocument to="../about">
72+
About
73+
</Link>
74+
</div>
75+
);
76+
}
77+
78+
act(() => {
79+
ReactDOM.render(
80+
<MemoryRouter initialEntries={["/home"]}>
81+
<Routes>
82+
<Route path="home" element={<Home />} />
83+
<Route path="about" element={<h1>About</h1>} />
84+
</Routes>
85+
</MemoryRouter>,
86+
node
87+
);
88+
});
89+
90+
let anchor = node.querySelector("a");
91+
expect(anchor).not.toBeNull();
92+
93+
let event: MouseEvent;
94+
act(() => {
95+
event = click(anchor);
96+
});
97+
98+
expect(event.defaultPrevented).toBe(false);
99+
});
100+
});
101+
63102
describe("when preventDefault is used on the click handler", () => {
64103
it("stays on the same page", () => {
65104
function Home() {

packages/react-router-dom/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ function isModifiedEvent(event: React.MouseEvent) {
200200

201201
export interface LinkProps
202202
extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href"> {
203+
reloadDocument?: boolean;
203204
replace?: boolean;
204205
state?: any;
205206
to: To;
@@ -210,7 +211,7 @@ export interface LinkProps
210211
*/
211212
export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
212213
function LinkWithRef(
213-
{ onClick, replace = false, state, target, to, ...rest },
214+
{ onClick, reloadDocument, replace = false, state, target, to, ...rest },
214215
ref
215216
) {
216217
let href = useHref(to);
@@ -219,7 +220,7 @@ export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
219220
event: React.MouseEvent<HTMLAnchorElement, MouseEvent>
220221
) {
221222
if (onClick) onClick(event);
222-
if (!event.defaultPrevented) {
223+
if (!event.defaultPrevented && !reloadDocument) {
223224
internalOnClick(event);
224225
}
225226
}

0 commit comments

Comments
 (0)