Skip to content

Commit

Permalink
Merge branch 'main' into suspense-for-client-only-components
Browse files Browse the repository at this point in the history
  • Loading branch information
tom-sherman committed Mar 10, 2023
2 parents 40486b3 + 8a07860 commit c5c8cce
Show file tree
Hide file tree
Showing 132 changed files with 1,609 additions and 639 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ tsconfig.tsbuildinfo
/scripts/playground/template/package-lock.json

/NOTES.md
/RELEASENOTES.md
3 changes: 3 additions & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
- bsharrow
- bsides
- bustamantedev
- buzinas
- c43721
- camiaei
- CanRau
Expand Down Expand Up @@ -463,6 +464,7 @@
- tjefferson08
- tombiju
- tombyrer
- TomerAberbach
- tom-sherman
- toyozaki
- turkerdev
Expand All @@ -488,6 +490,7 @@
- weavdale
- willhack
- willin
- wizardlyhel
- wKovacs64
- wladiston
- wtlin1228
Expand Down
15 changes: 13 additions & 2 deletions docs/file-conventions/remix-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,7 @@ to `"build/index.js"`.

## serverBuildTarget

<docs-warning>This option is deprecated and will likely be removed in a future
stable release. Use a combination of [`publicPath`][public-path],
<docs-warning>This option is deprecated and will be removed in the next major version release. Use a combination of [`publicPath`][public-path],
[`serverBuildPath`][server-build-path], [`serverConditions`][server-conditions],
[`serverDependenciesToBundle`][server-dependencies-to-bundle]
[`serverMainFields`][server-main-fields], [`serverMinify`][server-minify],
Expand All @@ -136,6 +135,18 @@ The `serverBuildTarget` can be one of the following:
- [`"node-cjs"`][node-cjs]
- [`"vercel"`][vercel]

**Migration Table:**

| serverBuildTarget | publicPath | serverBuildPath | serverConditions | serverMainFields | serverModuleFormat | serverPlatform | serverDependenciesToBundle | serverMinify |
| -------------------- | ------------------ | --------------------------------------- | ---------------- | ----------------------- | ------------------ | -------------- | -------------------------- | ------------ |
| `arc` | `/\_static/build/` | `server/index.js` | | `main, module` | `cjs` | `node` | | `false` |
| `cloudflare-pages` | `/build/` | `functions/[[path]].js` | `worker` | `browser, module, main` | `esm` | `neutral` | `all` | `true` |
| `cloudflare-workers` | `/build/` | `build/index.js` | `worker` | `browser, module, main` | `esm` | `neutral` | `all` | `true` |
| `deno` | `/build/` | `build/index.js` | `deno, worker` | `module, main` | `esm` | `neutral` | `all` | `false` |
| `netlify` | `/build/` | `.netlify/functions-internal/server.js` | | `main, module` | `cjs` | `node` | | `false` |
| `node-cjs` | `/build/` | `build/index.js` | | `main, module` | `cjs` | `node` | | `false` |
| `vercel` | `/build/` | `api/index.js` | | `main, module` | `cjs` | `node` | | `false` |

## serverConditions

The order of conditions to use when resolving server dependencies' `exports`
Expand Down
2 changes: 1 addition & 1 deletion docs/file-conventions/route-files-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ If you want one of the special characters Remix uses for these route conventions

## Folders for Organization

Routes can also be folders with a conventional node module resolution `index.tsx` file inside defining the route module. The rest of the files in the folder will not become routes. This allows you to organize your code closer to the routes that use them instead of repeating the feature names across other folders.
Routes can also be folders with a `route.tsx` file inside defining the route module. The rest of the files in the folder will not become routes. This allows you to organize your code closer to the routes that use them instead of repeating the feature names across other folders.

<docs-info>The files inside a folder have no meaning for the route paths, the route path is completely defined by the folder name</docs-info>

Expand Down
61 changes: 56 additions & 5 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-error>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` until v2.</docs-error>

---

<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 @@ -114,11 +118,62 @@ function SubmitButton() {
}
```

### Moving away from `transition.type`

The `type` field has been removed in the new `useNavigation` hook (which will replace `useTransition` in Remix v2). We've found that `state` is sufficient for almost all use-cases, and when it's not you can derive sub-types via `navigation.state` and other fields. Also note that the `loaderSubmission` type is now represented with `state: "loading"`. Here's a few examples:

```js
function Component() {
let navigation = useNavigation();

let isActionSubmission =
navigation.state === "submitting";

let isActionReload =
navigation.state === "loading" &&
navigation.formMethod != null &&
navigation.formMethod != "get" &&
// We had a submission navigation and are loading the submitted location
navigation.formAction === navigation.pathname;

let isActionRedirect =
navigation.state === "loading" &&
navigation.formMethod != null &&
navigation.formMethod != "get" &&
// We had a submission navigation and are now navigating to different location
navigation.formAction !== navigation.pathname;

let isLoaderSubmission =
navigation.state === "loading" &&
navigation.state.formMethod === "get" &&
// We had a loader submission and are navigating to the submitted location
navigation.formAction === navigation.pathname;

let isLoaderSubmissionRedirect =
navigation.state === "loading" &&
navigation.state.formMethod === "get" &&
// We had a loader submission and are navigating to a new location
navigation.formAction !== navigation.pathname;
}
```

## `transition.submission`

Any transition that started from a `<Form>` or `useSubmit` will have your form's submission attached to it. This is primarily useful to build "Optimistic UI" with the `submission.formData` [`FormData`][form-data] object.

TODO: Example
### Moving away from `transition.submission`

The `submission` field has been removed in the new `useNavigation` hook (which will replace `useTransition` in Remix v2) and the same sub-fields are now exposed directly on the `navigation`:

```js
function Component() {
let navigation = useNavigation();
// navigation.formMethod
// navigation.formAction
// navigation.formData
// navigation.formEncType
}
```

## `transition.location`

Expand Down Expand Up @@ -149,10 +204,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
3 changes: 2 additions & 1 deletion integration/abort-signal-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ let appFixture: AppFixture;

test.beforeAll(async () => {
fixture = await createFixture({
future: { v2_routeConvention: true },
files: {
"app/routes/index.jsx": js`
"app/routes/_index.jsx": js`
import { json } from "@remix-run/node";
import { useActionData, useLoaderData, Form } from "@remix-run/react";
Expand Down
1 change: 1 addition & 0 deletions integration/action-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ test.describe("actions", () => {

test.beforeAll(async () => {
fixture = await createFixture({
future: { v2_routeConvention: true },
files: {
"app/routes/urlencoded.jsx": js`
import { Form, useActionData } from "@remix-run/react";
Expand Down
3 changes: 2 additions & 1 deletion integration/bug-report-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ let appFixture: AppFixture;

test.beforeAll(async () => {
fixture = await createFixture({
future: { v2_routeConvention: true },
////////////////////////////////////////////////////////////////////////////
// 💿 Next, add files to this object, just like files in a real app,
// `createFixture` will make an app and run your tests against it.
////////////////////////////////////////////////////////////////////////////
files: {
"app/routes/index.jsx": js`
"app/routes/_index.jsx": js`
import { json } from "@remix-run/node";
import { useLoaderData, Link } from "@remix-run/react";
Expand Down
33 changes: 20 additions & 13 deletions integration/catch-boundary-data-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,26 @@ import { PlaywrightFixture } from "./helpers/playwright-fixture";
let fixture: Fixture;
let appFixture: AppFixture;

let ROOT_BOUNDARY_TEXT = "ROOT_TEXT";
let LAYOUT_BOUNDARY_TEXT = "LAYOUT_BOUNDARY_TEXT";
let OWN_BOUNDARY_TEXT = "OWN_BOUNDARY_TEXT";
let ROOT_BOUNDARY_TEXT = "ROOT_TEXT" as const;
let LAYOUT_BOUNDARY_TEXT = "LAYOUT_BOUNDARY_TEXT" as const;
let OWN_BOUNDARY_TEXT = "OWN_BOUNDARY_TEXT" as const;

let NO_BOUNDARY_LOADER = "/no/loader";
let HAS_BOUNDARY_LAYOUT_NESTED_LOADER = "/yes/loader-layout-boundary";
let HAS_BOUNDARY_NESTED_LOADER = "/yes/loader-self-boundary";
let NO_BOUNDARY_LOADER_FILE = "/no.loader" as const;
let NO_BOUNDARY_LOADER = "/no/loader" as const;

let HAS_BOUNDARY_LAYOUT_NESTED_LOADER_FILE =
"/yes.loader-layout-boundary" as const;
let HAS_BOUNDARY_LAYOUT_NESTED_LOADER = "/yes/loader-layout-boundary" as const;

let HAS_BOUNDARY_NESTED_LOADER_FILE = "/yes.loader-self-boundary" as const;
let HAS_BOUNDARY_NESTED_LOADER = "/yes/loader-self-boundary" as const;

let ROOT_DATA = "root data";
let LAYOUT_DATA = "root data";

test.beforeAll(async () => {
fixture = await createFixture({
future: { v2_routeConvention: true },
files: {
"app/root.jsx": js`
import { json } from "@remix-run/node";
Expand Down Expand Up @@ -69,7 +76,7 @@ test.beforeAll(async () => {
}
`,

"app/routes/index.jsx": js`
"app/routes/_index.jsx": js`
import { Link } from "@remix-run/react";
export default function Index() {
return (
Expand All @@ -82,7 +89,7 @@ test.beforeAll(async () => {
}
`,

[`app/routes${NO_BOUNDARY_LOADER}.jsx`]: js`
[`app/routes${NO_BOUNDARY_LOADER_FILE}.jsx`]: js`
export function loader() {
throw new Response("", { status: 401 });
}
Expand All @@ -91,7 +98,7 @@ test.beforeAll(async () => {
}
`,

[`app/routes${HAS_BOUNDARY_LAYOUT_NESTED_LOADER}.jsx`]: js`
[`app/routes${HAS_BOUNDARY_LAYOUT_NESTED_LOADER_FILE}.jsx`]: js`
import { useMatches } from "@remix-run/react";
export function loader() {
return "${LAYOUT_DATA}";
Expand All @@ -101,7 +108,7 @@ test.beforeAll(async () => {
}
export function CatchBoundary() {
let matches = useMatches();
let { data } = matches.find(match => match.id === "routes${HAS_BOUNDARY_LAYOUT_NESTED_LOADER}");
let { data } = matches.find(match => match.id === "routes${HAS_BOUNDARY_LAYOUT_NESTED_LOADER_FILE}");
return (
<div>
Expand All @@ -112,7 +119,7 @@ test.beforeAll(async () => {
}
`,

[`app/routes${HAS_BOUNDARY_LAYOUT_NESTED_LOADER}/index.jsx`]: js`
[`app/routes${HAS_BOUNDARY_LAYOUT_NESTED_LOADER_FILE}._index.jsx`]: js`
export function loader() {
throw new Response("", { status: 401 });
}
Expand All @@ -121,7 +128,7 @@ test.beforeAll(async () => {
}
`,

[`app/routes${HAS_BOUNDARY_NESTED_LOADER}.jsx`]: js`
[`app/routes${HAS_BOUNDARY_NESTED_LOADER_FILE}.jsx`]: js`
import { Outlet, useLoaderData } from "@remix-run/react";
export function loader() {
return "${LAYOUT_DATA}";
Expand All @@ -137,7 +144,7 @@ test.beforeAll(async () => {
}
`,

[`app/routes${HAS_BOUNDARY_NESTED_LOADER}/index.jsx`]: js`
[`app/routes${HAS_BOUNDARY_NESTED_LOADER_FILE}._index.jsx`]: js`
export function loader() {
throw new Response("", { status: 401 });
}
Expand Down
33 changes: 19 additions & 14 deletions integration/catch-boundary-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,23 @@ test.describe("CatchBoundary", () => {
let fixture: Fixture;
let appFixture: AppFixture;

let ROOT_BOUNDARY_TEXT = "ROOT_TEXT";
let OWN_BOUNDARY_TEXT = "OWN_BOUNDARY_TEXT";

let HAS_BOUNDARY_LOADER = "/yes/loader";
let HAS_BOUNDARY_ACTION = "/yes/action";
let NO_BOUNDARY_ACTION = "/no/action";
let NO_BOUNDARY_LOADER = "/no/loader";
let ROOT_BOUNDARY_TEXT = "ROOT_TEXT" as const;
let OWN_BOUNDARY_TEXT = "OWN_BOUNDARY_TEXT" as const;

let HAS_BOUNDARY_LOADER = "/yes/loader" as const;
let HAS_BOUNDARY_LOADER_FILE = "/yes.loader" as const;
let HAS_BOUNDARY_ACTION = "/yes/action" as const;
let HAS_BOUNDARY_ACTION_FILE = "/yes.action" as const;
let NO_BOUNDARY_ACTION = "/no/action" as const;
let NO_BOUNDARY_ACTION_FILE = "/no.action" as const;
let NO_BOUNDARY_LOADER = "/no/loader" as const;
let NO_BOUNDARY_LOADER_FILE = "/no.loader" as const;

let NOT_FOUND_HREF = "/not/found";

test.beforeAll(async () => {
fixture = await createFixture({
future: { v2_routeConvention: true },
files: {
"app/root.jsx": js`
import { json } from "@remix-run/node";
Expand Down Expand Up @@ -59,7 +64,7 @@ test.describe("CatchBoundary", () => {
}
`,

"app/routes/index.jsx": js`
"app/routes/_index.jsx": js`
import { Link, Form } from "@remix-run/react";
export default function() {
return (
Expand All @@ -85,7 +90,7 @@ test.describe("CatchBoundary", () => {
}
`,

[`app/routes${HAS_BOUNDARY_ACTION}.jsx`]: js`
[`app/routes${HAS_BOUNDARY_ACTION_FILE}.jsx`]: js`
import { Form } from "@remix-run/react";
export async function action() {
throw new Response("", { status: 401 })
Expand All @@ -104,7 +109,7 @@ test.describe("CatchBoundary", () => {
}
`,

[`app/routes${NO_BOUNDARY_ACTION}.jsx`]: js`
[`app/routes${NO_BOUNDARY_ACTION_FILE}.jsx`]: js`
import { Form } from "@remix-run/react";
export function action() {
throw new Response("", { status: 401 })
Expand All @@ -120,7 +125,7 @@ test.describe("CatchBoundary", () => {
}
`,

[`app/routes${HAS_BOUNDARY_LOADER}.jsx`]: js`
[`app/routes${HAS_BOUNDARY_LOADER_FILE}.jsx`]: js`
import { useCatch } from '@remix-run/react';
export function loader() {
throw new Response("", { status: 401 })
Expand All @@ -139,7 +144,7 @@ test.describe("CatchBoundary", () => {
}
`,

[`app/routes${HAS_BOUNDARY_LOADER}/child.jsx`]: js`
[`app/routes${HAS_BOUNDARY_LOADER_FILE}.child.jsx`]: js`
export function loader() {
throw new Response("", { status: 404 })
}
Expand All @@ -148,7 +153,7 @@ test.describe("CatchBoundary", () => {
}
`,

[`app/routes${NO_BOUNDARY_LOADER}.jsx`]: js`
[`app/routes${NO_BOUNDARY_LOADER_FILE}.jsx`]: js`
export function loader() {
throw new Response("", { status: 401 })
}
Expand All @@ -174,7 +179,7 @@ test.describe("CatchBoundary", () => {
}
`,

"app/routes/action/child-catch.jsx": js`
"app/routes/action.child-catch.jsx": js`
import { Form, useCatch, useLoaderData } from "@remix-run/react";
export function loader() {
Expand Down
3 changes: 2 additions & 1 deletion integration/cf-compiler-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ test.describe("cloudflare compiler", () => {

test.beforeAll(async () => {
projectDir = await createFixtureProject({
future: { v2_routeConvention: true },
setup: "cloudflare",
template: "cf-template",
files: {
Expand All @@ -34,7 +35,7 @@ test.describe("cloudflare compiler", () => {
"@remix-run/eslint-config": "0.0.0-local-version",
},
}),
"app/routes/index.jsx": js`
"app/routes/_index.jsx": js`
import fake from "worker-pkg";
import { content as browserPackage } from "browser-pkg";
import { content as esmOnlyPackage } from "esm-only-pkg";
Expand Down
Loading

0 comments on commit c5c8cce

Please sign in to comment.