Skip to content

Commit

Permalink
docs: use useNavigation instead of useTransition (#6800)
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelDeBoey authored Jul 10, 2023
1 parent 8e2e1ab commit c9648c7
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 32 deletions.
6 changes: 3 additions & 3 deletions docs/components/form.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function NewEvent() {
- Whether JavaScript is on the page or not, your data interactions created with `<Form>` and `action` will work.
- After a `<Form>` submission, all of the loaders on the page will be reloaded. This ensures that any updates to your data are reflected in the UI.
- `<Form>` automatically serializes your form's values (identically to the browser when not using JavaScript).
- You can build "optimistic UI" and pending indicators with [`useTransition`][usetransition].
- You can build "optimistic UI" and pending indicators with [`useNavigation`][usenavigation].

## `action`

Expand Down Expand Up @@ -98,12 +98,12 @@ When the `action` prop is omitted, `<Form>` and `<form>` will sometimes call dif

See also:

- [`useTransition`][usetransition]
- [`useNavigation`][usenavigation]
- [`useActionData`][useactiondata]
- [`useSubmit`][usesubmit]

[index query param]: ../guides/routing#what-is-the-index-query-param
[usetransition]: ../hooks/use-transition
[usenavigation]: ../hooks/use-navigation
[useactiondata]: ../hooks/use-action-data
[usesubmit]: ../hooks/use-submit
[http-verb]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
Expand Down
32 changes: 16 additions & 16 deletions docs/guides/data-writes.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,28 +309,28 @@ If you don't have the time or drive to do the rest of the job here, use `<Form r

<docs-info>We recommend always using capital-F Form, and if you want to let the browser handle the pending UI, use the <code>\<Form reloadDocument></code> prop.</docs-info>

Now let's add some pending UI so the user has a clue something happened when they submit. There's a hook called `useTransition`. When there is a pending form submission, Remix will give you the serialized version of the form as a <a href="https://developer.mozilla.org/en-US/docs/Web/API/FormData">`FormData`</a> object. You'll be most interested in the <a href="https://developer.mozilla.org/en-US/docs/Web/API/FormData/get">`formData.get()`</a> method.
Now let's add some pending UI so the user has a clue something happened when they submit. There's a hook called `useNavigation`. When there is a pending form submission, Remix will give you the serialized version of the form as a <a href="https://developer.mozilla.org/en-US/docs/Web/API/FormData">`FormData`</a> object. You'll be most interested in the <a href="https://developer.mozilla.org/en-US/docs/Web/API/FormData/get">`formData.get()`</a> method.

```tsx lines=[5,13,19,65-67]
import { json, redirect } from "@remix-run/node"; // or cloudflare/deno
import {
useActionData,
Form,
useTransition,
useNavigation,
} from "@remix-run/react";

// ...

export default function NewProject() {
// when the form is being processed on the server, this returns different
// transition states to help us build pending and optimistic UI.
const transition = useTransition();
// navigation states to help us build pending and optimistic UI.
const navigation = useNavigation();
const actionData = useActionData<typeof action>();

return (
<Form method="post">
<fieldset
disabled={transition.state === "submitting"}
disabled={navigation.state === "submitting"}
>
<p>
<label>
Expand Down Expand Up @@ -376,7 +376,7 @@ export default function NewProject() {

<p>
<button type="submit">
{transition.state === "submitting"
{navigation.state === "submitting"
? "Creating..."
: "Create"}
</button>
Expand All @@ -389,7 +389,7 @@ export default function NewProject() {

Pretty slick! Now when the user clicks "Create", the inputs go disabled, and the submit button's text changes. The whole operation should be faster now too since there's just one network request happening instead of a full page reload (which involves potentially more network requests, reading assets from the browser cache, parsing JavaScript, parsing CSS, etc.).

We didn't do much with `transition` on this page, but it's got all the information about the submission on `transition.submission`, including all of the values being processed on the server on `submission.formData`.
We didn't do much with `navigation` on this page, but it's got all the information about the submission, including all of the values being processed on the server in `navigation.formData`.

### Animating in the Validation Errors

Expand Down Expand Up @@ -426,13 +426,13 @@ Now we can wrap our old error messages in this new fancy component, and even tur

```tsx lines=[21-24,31-34,44-48,53-56]
export default function NewProject() {
const transition = useTransition();
const navigation = useNavigation();
const actionData = useActionData<typeof action>();

return (
<Form method="post">
<fieldset
disabled={transition.state === "submitting"}
disabled={navigation.state === "submitting"}
>
<p>
<label>
Expand All @@ -456,7 +456,7 @@ export default function NewProject() {

{actionData?.errors.name ? (
<ValidationMessage
isSubmitting={transition.state === "submitting"}
isSubmitting={navigation.state === "submitting"}
error={actionData?.errors?.name}
/>
) : null}
Expand All @@ -478,13 +478,13 @@ export default function NewProject() {
</p>

<ValidationMessage
isSubmitting={transition.state === "submitting"}
isSubmitting={navigation.state === "submitting"}
error={actionData?.errors.description}
/>

<p>
<button type="submit">
{transition.state === "submitting"
{navigation.state === "submitting"
? "Creating..."
: "Create"}
</button>
Expand All @@ -503,14 +503,14 @@ Boom! Fancy UI without having to change anything about how we communicate with t

- Once that worked, we used JavaScript to submit the form by changing `<form>` to `<Form>`, but we didn't have to do anything else!

- Now that there was a stateful page with React, we added loading indicators and animation for the validation errors by simply asking Remix for the state of the transition.
- Now that there was a stateful page with React, we added loading indicators and animation for the validation errors by simply asking Remix for the state of the navigation.

From your components perspective, all that happened was the `useTransition` hook caused a state update when the form was submitted, and then another state update when the data came back. Of course, a lot more happened inside of Remix, but as far as your component is concerned, that's it. Just a couple of state updates. This makes it really easy to dress up any user flow.
From your components perspective, all that happened was the `useNavigation` hook caused a state update when the form was submitted, and then another state update when the data came back. Of course, a lot more happened inside of Remix, but as far as your component is concerned, that's it. Just a couple of state updates. This makes it really easy to dress up any user flow.

## See also

- [Form][form]
- [useTransition][use-transition]
- [useNavigation][use-navigation]
- [Actions][actions]
- [Loaders][loaders]
- [`useSubmit()`][use-submit]
Expand All @@ -519,6 +519,6 @@ From your components perspective, all that happened was the `useTransition` hook
[form]: ../components/form
[use-submit]: ../hooks/use-submit
[use-fetcher]: ../hooks/use-fetcher
[use-transition]: ../hooks/use-transition
[use-navigation]: ../hooks/use-navigation
[actions]: ../route/action
[loaders]: ../route/loader
4 changes: 2 additions & 2 deletions docs/hooks/use-action-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ If you're using `<Form>` and don't care to support the cases above, you don't ne
See also:

- [`action`][action]
- [`useTransition`][usetransition]
- [`useNavigation`][usenavigation]

[action]: ../route/action
[usetransition]: ../hooks/use-transition
[usenavigation]: ../hooks/use-navigation
[rr-useactiondata]: https://reactrouter.com/hooks/use-action-data
4 changes: 2 additions & 2 deletions docs/hooks/use-fetcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ It is common for Remix newcomers to see this hook and think it is the primary wa
- [`useLoaderData`][useloaderdata]
- [`Form`][form]
- [`useActionData`][useactiondata]
- [`useTransition`][usetransition]
- [`useNavigation`][usenavigation]

If you're building a highly interactive, "app-like" user interface, you will use `useFetcher` often.

Expand Down Expand Up @@ -435,7 +435,7 @@ function CitySearchCombobox() {

[form]: ../components/form
[index query param]: ../guides/routing#what-is-the-index-query-param
[usetransition]: ./use-transition
[usenavigation]: ./use-navigation
[useactiondata]: ./use-action-data
[useloaderdata]: ./use-loader-data
[v2guide]: ../pages/v2#usefetcher
12 changes: 6 additions & 6 deletions docs/hooks/use-submit.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This is useful whenever you need to programmatically submit a form. For example,
```tsx filename=app/routes/prefs.tsx lines=[3,15,19]
import type { ActionArgs } from "@remix-run/node"; // or cloudflare/deno
import { json } from "@remix-run/node"; // or cloudflare/deno
import { useSubmit, useTransition } from "@remix-run/react";
import { useSubmit, useNavigation } from "@remix-run/react";

export async function loader() {
return json(await getUserPreferences());
Expand All @@ -27,7 +27,7 @@ export async function action({ request }: ActionArgs) {

function UserPreferences() {
const submit = useSubmit();
const transition = useTransition();
const navigation = useNavigation();

function handleChange(event) {
submit(event.currentTarget, { replace: true });
Expand All @@ -39,7 +39,7 @@ function UserPreferences() {
<input type="checkbox" name="darkMode" value="on" />{" "}
Dark Mode
</label>
{transition.state === "submitting" ? (
{navigation.state === "submitting" ? (
<p>Saving...</p>
) : null}
</Form>
Expand All @@ -50,7 +50,7 @@ function UserPreferences() {
This can also be useful if you'd like to automatically sign someone out of your website after a period of inactivity. In this case, we've defined inactivity as the user hasn't navigated to any other pages after 5 minutes.

```tsx lines=[1,10,15]
import { useSubmit, useTransition } from "@remix-run/react";
import { useSubmit, useNavigation } from "@remix-run/react";
import { useEffect } from "react";

function AdminPage() {
Expand All @@ -60,15 +60,15 @@ function AdminPage() {

function useSessionTimeout() {
const submit = useSubmit();
const transition = useTransition();
const navigation = useNavigation();

useEffect(() => {
const timer = setTimeout(() => {
submit(null, { method: "post", action: "/logout" });
}, 5 * 60_000);

return () => clearTimeout(timer);
}, [submit, transition]);
}, [submit, navigation]);
}
```

Expand Down
2 changes: 1 addition & 1 deletion docs/pages/technical-explanation.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Taking our route module from before, here are a few small, but useful UX improve
export default function Projects() {
const projects = useLoaderData<typeof loader>();
const actionData = useActionData<typeof action>();
const { state } = useTransition();
const { state } = useNavigation();
const busy = state === "submitting";
const inputRef = React.useRef();

Expand Down
4 changes: 2 additions & 2 deletions integration/link-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ test.describe("route module link export", () => {

"app/routes/gists.jsx": js`
import { json } from "@remix-run/node";
import { Link, Outlet, useLoaderData, useTransition } from "@remix-run/react";
import { Link, Outlet, useLoaderData, useNavigation } from "@remix-run/react";
import stylesHref from "~/gists.css";
export function links() {
return [{ rel: "stylesheet", href: stylesHref }];
Expand All @@ -343,7 +343,7 @@ test.describe("route module link export", () => {
breadcrumb: () => <Link to="/gists">Gists</Link>,
};
export default function Gists() {
let locationPending = useTransition().location;
let locationPending = useNavigation().location;
let { users } = useLoaderData();
return (
<div data-test-id="/gists">
Expand Down

0 comments on commit c9648c7

Please sign in to comment.