Skip to content

Commit

Permalink
feat: added reloadDocument to <Link> and <NavLink> (#8283)
Browse files Browse the repository at this point in the history
* feat: added forceDocument to `<Link>`

* renamed to reloadDocument

* chore(docs): added docs on reloadDocument

* chore(docs): typos

Co-authored-by: Ryan Florence <[email protected]>
  • Loading branch information
2 people authored and chaance committed Nov 9, 2021
1 parent 739af00 commit b7d0e1c
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 15 deletions.
6 changes: 3 additions & 3 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,17 +252,17 @@ interface LinkProps
"href"
> {
replace?: boolean;
state?: State;
state?: any;
to: To;
reloadDocument?: boolean;
}

type State = object | null;
type To = Partial<Location> | string;
```

</details>

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.
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>`).

```tsx
import * as React from "react";
Expand Down
59 changes: 49 additions & 10 deletions packages/react-router-dom/__tests__/link-click-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 <Link> click", () => {
Expand Down Expand Up @@ -51,15 +51,54 @@ describe("A <Link> 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 (
<div>
<h1>Home</h1>
<Link reloadDocument to="../about">
About
</Link>
</div>
);
}

act(() => {
ReactDOM.render(
<MemoryRouter initialEntries={["/home"]}>
<Routes>
<Route path="home" element={<Home />} />
<Route path="about" element={<h1>About</h1>} />
</Routes>
</MemoryRouter>,
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() {
Expand Down
5 changes: 3 additions & 2 deletions packages/react-router-dom/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ function isModifiedEvent(event: React.MouseEvent) {

export interface LinkProps
extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href"> {
reloadDocument?: boolean;
replace?: boolean;
state?: any;
to: To;
Expand All @@ -210,7 +211,7 @@ export interface LinkProps
*/
export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
function LinkWithRef(
{ onClick, replace = false, state, target, to, ...rest },
{ onClick, reloadDocument, replace = false, state, target, to, ...rest },
ref
) {
let href = useHref(to);
Expand All @@ -219,7 +220,7 @@ export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
event: React.MouseEvent<HTMLAnchorElement, MouseEvent>
) {
if (onClick) onClick(event);
if (!event.defaultPrevented) {
if (!event.defaultPrevented && !reloadDocument) {
internalOnClick(event);
}
}
Expand Down

0 comments on commit b7d0e1c

Please sign in to comment.