Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: use useNavigation instead of useTransition #5692

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -313,22 +313,22 @@ 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,
useActionData,
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 (
Expand Down Expand Up @@ -380,7 +380,7 @@ export default function NewProject() {

<p>
<button type="submit">
{transition.state === "submitting"
{navigation.state === "submitting"
? "Creating..."
: "Create"}
</button>
Expand All @@ -393,7 +393,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 the values being processed on the server in `navigation.formData`.

### Animating in the Validation Errors

Expand Down Expand Up @@ -430,13 +430,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 @@ -460,7 +460,7 @@ export default function NewProject() {

{actionData?.errors.name ? (
<ValidationMessage
isSubmitting={transition.state === "submitting"}
isSubmitting={navigation.state === "submitting"}
error={actionData?.errors?.name}
/>
) : null}
Expand All @@ -482,13 +482,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 @@ -507,14 +507,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 component's 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 @@ -523,6 +523,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 @@ -24,7 +24,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 @@ -434,6 +434,6 @@ 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
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
8 changes: 4 additions & 4 deletions docs/hooks/use-transition.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ title: useTransition

# `useTransition`

<docs-warning>This API will be removed in v2 in favor of [`useNavigation`][use-navigation].
You can start using the new `useNavigation` hook today to make upgrading in the future easy,
but you can keep using `useTransition` before v2.</docs-warning>

<docs-success>Watch the <a href="https://www.youtube.com/playlist?list=PLXoynULbYuEDG2wBFSZ66b85EIspy3fy6">📼 Remix Singles</a>: <a href="https://www.youtube.com/watch?v=y4VLIFjFq8k&list=PLXoynULbYuEDG2wBFSZ66b85EIspy3fy6">Pending UI</a>, <a href="https://www.youtube.com/watch?v=bMLej7bg5Zo&list=PLXoynULbYuEDG2wBFSZ66b85EIspy3fy6">Clearing Inputs After Form Submissions</a>, and <a href="https://www.youtube.com/watch?v=EdB_nj01C80&list=PLXoynULbYuEDG2wBFSZ66b85EIspy3fy6">Optimistic UI</a></docs-success>

This hook tells you everything you need to know about a page transition to build pending navigation indicators and optimistic UI on data mutations. Things like:
Expand Down Expand Up @@ -149,10 +153,6 @@ function PendingLink({ to, children }) {

Note that this link will not appear "pending" if a form is being submitted to the URL the link points to, because we only do this for "loading" states. The form will contain the pending UI for when the state is "submitting", once the action is complete, then the link will go pending.

## v2 deprecation

This API will be removed in v2 in favor of [`useNavigation`][use-navigation]. You can start using the new `useNavigation` hook today to make upgrading in the future easy, but you can keep using `useTransition` before v2.

[usefetcher]: ./use-fetcher
[form-data]: https://developer.mozilla.org/en-US/docs/Web/API/FormData
[use-navigation]: ./use-navigation
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