Skip to content

Commit

Permalink
docs: rearrange docs, give everything its own page (#4821)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanflorence committed Dec 10, 2022
1 parent 37029d0 commit 3419354
Show file tree
Hide file tree
Showing 71 changed files with 4,507 additions and 3,897 deletions.
1,373 changes: 49 additions & 1,324 deletions docs/api/conventions.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/api/index.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
title: API
order: 3
hidden: true
---
2,573 changes: 74 additions & 2,499 deletions docs/api/remix.md

Large diffs are not rendered by default.

105 changes: 105 additions & 0 deletions docs/components/form.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
title: Form
---

# `<Form>`

<docs-success>Watch the <a href="https://www.youtube.com/playlist?list=PLXoynULbYuEDG2wBFSZ66b85EIspy3fy6">📼 Remix Singles</a>: <a href="https://www.youtube.com/watch?v=Iv25HAHaFDs&list=PLXoynULbYuEDG2wBFSZ66b85EIspy3fy6">Data Mutations with Form + action</a>, <a href="https://www.youtube.com/watch?v=w2i-9cYxSdc&list=PLXoynULbYuEDG2wBFSZ66b85EIspy3fy6">Multiple Forms and Single Button Mutations</a> and <a href="https://www.youtube.com/watch?v=bMLej7bg5Zo&list=PLXoynULbYuEDG2wBFSZ66b85EIspy3fy6">Clearing Inputs After Form Submissions</a></docs-success>

The `<Form>` component is a declarative way to perform data mutations: creating, updating, and deleting data. While it might be a mind-shift to think about these tasks as "navigation", it's how the web has handled mutations since before JavaScript was created!

```tsx
import { Form } from "@remix-run/react";

function NewEvent() {
return (
<Form method="post" action="/events">
<input type="text" name="title" />
<input type="text" name="description" />
</Form>
);
}
```

- 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]

## `action`

Most of the time you can omit this prop. Forms without an action prop (`<Form method="post">`) will automatically post to the same route within which they are rendered. This makes collocating your component, your data reads, and your data writes a snap.

If you need to post to a different route, then add an action prop:

```tsx
<Form action="/projects/new" method="post" />
```

When a POST is made to a URL, multiple routes in your route hierarchy will match the URL. Unlike a GET to loaders, where all of them are called to build the UI, _only one action is called_. The route called will be the deepest matching route, unless the deepest matching route is an "index route". In this case, it will post to the parent route of the index route (because they share the same URL).

If you want to post to an index route use `?index` in the action: `<Form action="/accounts?index" method="post" />`

| action url | route action |
| ----------------- | -------------------------- |
| `/accounts?index` | `routes/accounts/index.js` |
| `/accounts` | `routes/accounts.js` |

See also:

- [`?index` query param][index query param]

## `method`

This determines the [HTTP verb][http-verb] to be used: get, post, put, patch, delete. The default is "get".

```tsx
<Form method="post" />
```

Native `<form>` only supports get and post, so if you want your form to work with JavaScript on or off the page you'll need to stick with those two.

Without JavaScript, Remix will turn non-get requests into "post", but you'll still need to instruct your server with a hidden input like `<input type="hidden" name="_method" value="delete" />`. If you always include JavaScript, you don't need to worry about this.

<docs-info>We generally recommend sticking with "get" and "post" because the other verbs are not supported by HTML</docs-info>

## `encType`

Defaults to `application/x-www-form-urlencoded`, use `multipart/form-data` for file uploads.

## `replace`

```tsx
<Form replace />
```

Instructs the form to replace the current entry in the history stack, instead of pushing the new entry. If you expect a form to be submitted multiple times you may not want the user to have to click "back" for every submission to get to the previous page.

<docs-warning>This has no effect without JavaScript on the page.</docs-warning>

## `reloadDocument`

If true, it will submit the form with the browser instead of JavaScript, even if JavaScript is on the page.

```tsx
<Form reloadDocument />
```

<docs-info>This is recommended over <code>\<form></code></docs-info>

When the `action` prop is omitted, `<Form>` and `<form>` will sometimes call different actions depending on what the current URL is.

- `<form>` uses the current URL as the default which can lead to surprising results: forms inside parent routes will post to the child action if you're at the child's URL and the parents action when you're at the parent's URL. This means as the user navigates, the form's behavior changes.
- `<Form>` will always post to the route's action, independent of the URL. A form in a parent route will always post to the parent, even if you're at the child's URL.

See also:

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

[index query param]: ../guides/routing#what-is-the-index-query-param
[usetransition]: ../hooks/use-transition
[useactiondata]: ../hooks/use-action-data
[usesubmit]: ../hooks/use-submit
[http-verb]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
4 changes: 4 additions & 0 deletions docs/components/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: Components
order: 12
---
42 changes: 42 additions & 0 deletions docs/components/link.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: Link
---

# `<Link>`

This component renders an anchor tag and is the primary way the user will navigate around your website. Anywhere you would have used `<a href="...">` you should now use `<Link to="..."/>` to get all the performance benefits of client-side routing in Remix.

It wraps React Router's Link with some extra behavior around resource prefetching.

```tsx
import { Link } from "@remix-run/react";

export default function GlobalNav() {
return (
<nav>
<Link to="/dashboard">Dashboard</Link>{" "}
<Link to="/account">Account</Link>{" "}
<Link to="/support">Support</Link>
</nav>
);
}
```

In our effort to remove all loading states from your UI, `Link` can automatically prefetch all the resources the next page needs: JavaScript modules, stylesheets, and data. This prop controls if and when that happens.

```tsx
<>
<Link /> {/* defaults to "none" */}
<Link prefetch="none" />
<Link prefetch="intent" />
<Link prefetch="render" />
</>
```

- **"none"** - Default behavior. This will prevent any prefetching from happening. This is recommended when linking to pages that require a user session that the browser won't be able to prefetch anyway.
- **"intent"** - Recommended if you want to prefetch. Fetches when Remix thinks the user intends to visit the link. Right now the behavior is simple: if they hover or focus the link it will prefetch the resources. In the future we hope to make this even smarter. Links with large click areas/padding get a bit of a head start. It is worth noting that when using `prefetch="intent"`, `<link rel="prefetch">` elements will be inserted on hover/focus and removed if the `<Link>` loses hover/focus. Without proper `cache-control` headers on your loaders this could result in repeated prefetch loads if a user continually hovers on and off a link.
- **"render"** - Fetches when the link is rendered.

<docs-error>You may need to use the <code>:last-of-type</code> selector instead of <code>:last-child</code> when styling child elements inside of your links</docs-error>

Remix uses the browser's cache for prefetching with HTML `<link rel="prefetch"/>` tags, which provides a lot of subtle benefits (like respecting HTTP cache headers, doing the work in browser idle time, using a different thread than your app, etc.) but the implementation might mess with your CSS since the link tags are rendered inside of your anchor tag. This means `a *:last-child {}` style selectors won't work. You'll need to change them to `a *:last-of-type {}` and you should be good. We will eventually get rid of this limitation.
24 changes: 24 additions & 0 deletions docs/components/links.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: Links
---

# `<Links />`

The `<Links/>` component renders all of the `<link>` tags created by your route module [`links`][links] export. You should render it inside the `<head>` of your HTML, usually in `app/root.tsx`.

```tsx filename=root.tsx lines=[7]
import { Links } from "@remix-run/react";

export default function Root() {
return (
<html>
<head>
<Links />
</head>
<body></body>
</html>
);
}
```

[links]: ../route/links
22 changes: 22 additions & 0 deletions docs/components/live-reload.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: LiveReload
---

# `<LiveReload />`

This component connects your app to the Remix asset server and automatically reloads the page when files change in development. In production it renders `null`, so you can safely render it always in your root route.

```tsx filename=root.tsx lines=[8]
import { LiveReload } from "@remix-run/react";

export default function Root() {
return (
<html>
<head />
<body>
<LiveReload />
</body>
</html>
);
}
```
24 changes: 24 additions & 0 deletions docs/components/meta.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: Meta
---

# `<Meta />`

This component renders all of the `<meta>` tags created by your route module [`meta`][meta] export. You should render it inside the `<head>` of your HTML, usually in `app/root.tsx`.

```tsx filename=root.tsx lines=[7]
import { Meta } from "@remix-run/react";

export default function Root() {
return (
<html>
<head>
<Meta />
</head>
<body></body>
</html>
);
}
```

[meta]: ../route/meta
69 changes: 69 additions & 0 deletions docs/components/nav-link.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: NavLink
---

# `<NavLink>`

A `<NavLink>` is a special kind of `<Link>` that knows whether or not it is "active". This is useful when building a navigation menu, such as a breadcrumb or a set of tabs where you'd like to show which of them is currently selected. It also provides useful context for assistive technology like screen readers.

By default, an `active` class is added to a `<NavLink>` component when it is active. You can pass a function as children to customize the content of the `<NavLink>` component based on their active state, specially useful to change styles on internal elements.

```tsx
import { NavLink } from "@remix-run/react";

function NavList() {
// This styling will be applied to a <NavLink> when the
// route that it links to is currently selected.
const activeStyle = {
textDecoration: "underline",
};
const activeClassName = "underline";
return (
<nav>
<ul>
<li>
<NavLink
to="messages"
style={({ isActive }) =>
isActive ? activeStyle : undefined
}
>
Messages
</NavLink>
</li>
<li>
<NavLink
to="tasks"
className={({ isActive }) =>
isActive ? activeClassName : undefined
}
>
Tasks
</NavLink>
</li>
<li>
<NavLink to="tasks">
{({ isActive }) => (
<span
className={
isActive ? activeClassName : undefined
}
>
Tasks
</span>
)}
</NavLink>
</li>
</ul>
</nav>
);
}
```

If the `end` prop is used, it will ensure this component isn't matched as "active" when its descendant paths are matched. For example, to render a link that is only active at the website root and not any other URLs, you can use:

```tsx
<NavLink to="/" end>
Home
</NavLink>
```
9 changes: 9 additions & 0 deletions docs/components/outlet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: Outlet
---

# `<Outlet>`

Re-export of [React Router Outlet][rr-outlet].

[rr-outlet]: https://reactrouter.com/en/main/components/outlet
15 changes: 15 additions & 0 deletions docs/components/prefetch-page-links.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: PrefetchPageLinks
---

# `<PrefetchPageLinks />`

This component enables prefetching of all assets for a page to enable an instant navigation to that page. It does this by rendering `<link rel="prefetch">` and `<link rel="modulepreload"/>` tags for all the assets (data, modules, css) of a given page.

`<Link rel="prefetch">` uses this internally, but you can render it to prefetch a page for any other reason.

```tsx
<PrefetchPageLinks page="/absolute/path/to/your-path" />
```

**Note:** You need to use an absolute path.
26 changes: 26 additions & 0 deletions docs/components/scripts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
title: Scripts
---

# `<Scripts />`

This component renders the client runtime of your app. You should render it inside the `<body>` of your HTML, usually in `app/root.tsx`.

```tsx filename=root.tsx lines=[8]
import { Scripts } from "@remix-run/react";

export default function Root() {
return (
<html>
<head />
<body>
<Scripts />
</body>
</html>
);
}
```

If you don't render the `<Scripts/>` component, your app will still work like a traditional web app without JavaScript, relying solely on HTML and browser behaviors. That's cool, but we personally have bigger goals than spinning favicons, so we recommend adding JavaScript to your app 😎

[meta]: ../route/meta
21 changes: 21 additions & 0 deletions docs/components/scroll-restoration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: ScrollRestoration
---

# `<ScrollRestoration>`

This component will emulate the browser's scroll restoration on location changes. Hopefully you never notice this component at all!

It must be the last element on the page, right before the `<Scripts/>` tag:

```tsx lines=[4,5]
<html>
<body>
{/* ... */}
<ScrollRestoration />
<Scripts />
</body>
</html>
```

In order to avoid the typical client-side routing "scroll flash" jank on refresh or clicking back into the app from a different domain, this component restores scroll _before_ React hydration.

0 comments on commit 3419354

Please sign in to comment.