Skip to content

Commit

Permalink
Remove useBlocker, usePrompt, and Prompt
Browse files Browse the repository at this point in the history
This commit removes anything to do with blocking. The behavior isn't solid yet in the current release, and we don't want it to block shipping v6 stable.

Will revisit post v6 stable.
  • Loading branch information
mjackson committed Oct 15, 2021
1 parent 94e329a commit 256cad7
Show file tree
Hide file tree
Showing 9 changed files with 4 additions and 287 deletions.
147 changes: 0 additions & 147 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,6 @@ There are a few low-level APIs that we use internally that may also prove useful
- [`useLinkPressHandler`](#uselinkpresshandler) - returns an event handler to for navigation when building a custom `<Link>` in `react-router-native`
- [`resolvePath`](#resolvepath) - resolves a relative path against a given URL pathname

### Confirming Navigation

Sometimes you need to confirm navigation before it actually happens. For example, if the user has entered some data into a form on the current page, you may want to prompt them to save the data before they navigate to a different page.

- [`usePrompt`](#useprompt) and [`<Prompt>`](#prompt) trigger a platform-native confirmation prompt when the user tries to navigate away from the current page
- [`useBlocker`](#useblocker) is a low-level interface that lets you keep the user on the same page and execute a function that will be called when they try to navigate away

### Search Parameters

Access to the URL [search parameters](https://developer.mozilla.org/en-US/docs/Web/API/URL/searchParams) is provided via [the `useSearchParams` hook](#usesearchparams).
Expand Down Expand Up @@ -514,60 +507,6 @@ function App() {
}
```

### `<Prompt>`

> **Note:**
>
> This is the web version of `<Prompt>`. For the React Native version,
> [go here](#prompt-native).
<details>
<summary>Type declaration</summary>

```tsx
declare function Prompt(props: PromptProps): null;

interface PromptProps {
message: string;
when?: boolean;
}
```

</details>

A `<Prompt>` is the declarative version of [`usePrompt`](#useprompt). It doesn't render anything. It just calls `usePrompt` with its props.

> **Note:**
>
> Having a component-based version of the `usePrompt` hook makes it easier to
> use this feature in a [`React.Component`](https://reactjs.org/docs/react-component.html)
> subclass where hooks are not able to be used.
<a name="prompt-native"></a>

### `<Prompt>` (React Native)

> **Note:**
>
> This is the React Native version of `<Prompt>`. For the web version,
> [go here](#prompt).
<details>
<summary>Type declaration</summary>

```tsx
declare function Prompt(props: PromptProps): null;

interface PromptProps {
message: string;
when?: boolean;
}
```

</details>

A `<Prompt>` is the declarative version of [`usePrompt`](#useprompt). It doesn't render anything. It just calls `usePrompt` with its props.

### `<Router>`

<details>
Expand Down Expand Up @@ -869,23 +808,6 @@ interface Path {

The [`useResolvedPath` hook](#useresolvedpath) uses `resolvePath` internally to resolve the pathname. If `to` contains a pathname, it is resolved against the current route pathname. Otherwise, it is resolved against the current URL (`location.pathname`).

### `useBlocker`

<details>
<summary>Type declaration</summary>

```tsx
declare function useBlocker(blocker: Blocker, when?: boolean): void;

interface Blocker<S extends State = object | null> {
(tx: Transition<S>): void;
}
```

</details>

`useBlocker` is a low-level hook that allows you to block navigation away from the current page, i.e. prevent the current location from changing. This is probably something you don't ever want to do unless you also display a confirmation dialog to the user to help them understand why their navigation attempt was blocked. In these cases, you probably want to use [`usePrompt`](#useprompt) or [`<Prompt>`](#prompt) instead.

### `useHref`

<details>
Expand Down Expand Up @@ -1148,75 +1070,6 @@ function App() {
}
```

### `usePrompt`

> **Note:**
>
> This is the web version of `usePrompt`. For the React Native version,
> [go here](#useprompt-native).
<details>
<summary>Type declaration</summary>

```tsx
declare function usePrompt(message: string, when?: boolean): void;
```

</details>

The `usePrompt` hook may be used to confirm navigation before the user navigates away from the current page. This is useful when someone has entered unsaved data into a form, and you'd like to prompt them before they accidentally leave or close the tab and lose their work.

```tsx
import React from "react";
import { usePrompt } from "react-router-dom";

function SignupForm() {
let [formData, setFormData] = React.useState(null);
usePrompt("Are you sure you want to leave?", formData != null);
// ...
}
```

`usePrompt` uses [`window.confirm`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm) on the web and [the `Alert` module](https://reactnative.dev/docs/alert) on React Native to display native, accessible confirm dialogs.

> **Note:**
>
> If you need a more custom dialog box, you will have to use [`useBlocker`](#useblocker)
> directly and handle accessibility issues yourself.
<a name="useprompt-native"></a>

### `usePrompt` (React Native)

> **Note:**
>
> This is the React Native version of `usePrompt`. For the web version,
> [go here](#useprompt).
<details>
<summary>Type declaration</summary>

```tsx
declare function usePrompt(message: string, when?: boolean): void;
```

</details>

The `usePrompt` hook may be used to confirm navigation before the user navigates away from the current page. This is useful when someone has entered unsaved data into a form, and you'd like to prompt them before they accidentally leave or close the tab and lose their work.

```tsx
import React from "react";
import { usePrompt } from "react-router-native";

function SignupForm() {
let [formData, setFormData] = React.useState(null);
usePrompt("Are you sure you want to leave?", formData != null);
// ...
}
```

The React Native version of `usePrompt` calls the `alert` method from the [React Native Alert class](https://reactnative.dev/docs/alert).

### `useResolvedPath`

<details>
Expand Down
1 change: 0 additions & 1 deletion docs/guides/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ build a certain capability or feature of your app with React Router.
## Common User Flows

- [Login and Authentication](user-flows/login-and-auth.md)
- [Forms and Prompts](user-flows/forms-and-prompts.md)
- [Transitions and Animation](user-flows/transitions-and-animation.md)
- [Passing Data Between Routes Using `location.state`](user-flows/passing-data.md)
- [Persisting Data Using `location.key`](user-flows/persisting-data.md)
Expand Down
8 changes: 0 additions & 8 deletions docs/guides/user-flows/forms-and-prompts.md

This file was deleted.

5 changes: 1 addition & 4 deletions packages/react-router-dom/__tests__/link-push-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,8 @@ function createMockHistory({ pathname = "/", search = "", hash = "" }) {
forward() {},
listen() {
return () => {};
},
block() {
return () => {};
}
} as History;
} as Omit<History, "block">;
}

describe("Link push and replace", () => {
Expand Down
34 changes: 0 additions & 34 deletions packages/react-router-dom/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
matchPath,
resolvePath,
renderMatches,
useBlocker,
useHref,
useInRouterContext,
useLocation,
Expand Down Expand Up @@ -61,7 +60,6 @@ export {
matchPath,
renderMatches,
resolvePath,
useBlocker,
useHref,
useInRouterContext,
useLocation,
Expand Down Expand Up @@ -313,23 +311,6 @@ if (__DEV__) {
NavLink.displayName = "NavLink";
}

export interface PromptProps {
message: string;
when?: boolean;
}

/**
* A declarative interface for showing a window.confirm dialog with the given
* message when the user tries to navigate away from the current page.
*
* This also serves as a reference implementation for anyone who wants to
* create their own custom prompt component.
*/
export function Prompt({ message, when }: PromptProps) {
usePrompt(message, when);
return null;
}

////////////////////////////////////////////////////////////////////////////////
// HOOKS
////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -379,21 +360,6 @@ export function useLinkClickHandler<
);
}

/**
* Prevents navigation away from the current page using a window.confirm prompt
* with the given message.
*/
export function usePrompt(message: string, when = true) {
let blocker = React.useCallback(
tx => {
if (window.confirm(message)) tx.retry();
},
[message]
);

useBlocker(blocker, when);
}

/**
* A convenient wrapper for reading and writing search parameters via the
* URLSearchParams interface.
Expand Down
6 changes: 0 additions & 6 deletions packages/react-router-dom/server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,6 @@ export function StaticRouter({
`You cannot use navigator.forward() on the server because it is a stateless ` +
`environment.`
);
},
block() {
throw new Error(
`You cannot use navigator.block() on the server because it is a stateless ` +
`environment.`
);
}
};

Expand Down
41 changes: 0 additions & 41 deletions packages/react-router-native/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {
matchPath,
resolvePath,
renderMatches,
useBlocker,
useHref,
useInRouterContext,
useLocation,
Expand Down Expand Up @@ -54,7 +53,6 @@ export {
matchPath,
resolvePath,
renderMatches,
useBlocker,
useHref,
useInRouterContext,
useLocation,
Expand Down Expand Up @@ -147,23 +145,6 @@ export function Link({
return <TouchableHighlight {...rest} onPress={handlePress} />;
}

export interface PromptProps {
message: string;
when?: boolean;
}

/**
* A declarative interface for showing an Alert dialog with the given
* message when the user tries to navigate away from the current screen.
*
* This also serves as a reference implementation for anyone who wants
* to create their own custom prompt component.
*/
export function Prompt({ message, when }: PromptProps) {
usePrompt(message, when);
return null;
}

////////////////////////////////////////////////////////////////////////////////
// HOOKS
////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -264,28 +245,6 @@ function trimScheme(url: string) {
return url.replace(/^.*?:\/\//, "");
}

/**
* Prompts the user with an Alert before they leave the current screen.
*/
export function usePrompt(message: string, when = true) {
let blocker = React.useCallback(
tx => {
Alert.alert("Confirm", message, [
{ text: "Cancel", onPress() {} },
{
text: "OK",
onPress() {
tx.retry();
}
}
]);
},
[message]
);

useBlocker(blocker, when);
}

/**
* A convenient wrapper for accessing individual query parameters via the
* URLSearchParams interface.
Expand Down
5 changes: 1 addition & 4 deletions packages/react-router/__tests__/navigate-push-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,8 @@ function createMockHistory(initialLocation: Partial<History["location"]>) {
forward() {},
listen() {
return () => {};
},
block() {
return () => {};
}
} as History;
} as Omit<History, "block">;
}

describe("navigate", () => {
Expand Down
Loading

1 comment on commit 256cad7

@joshcomley
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where have these gone to?

Please sign in to comment.