-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: lazy data via `defer()` and `<Await>` chore: bump @remix-run/router to 1.3.0-pre.2 chore: bump react-router-dom to 6.7.0-pre.3
- Loading branch information
1 parent
efe3e28
commit be232a0
Showing
27 changed files
with
2,312 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
--- | ||
"remix": patch | ||
"@remix-run/cloudflare": patch | ||
"@remix-run/deno": patch | ||
"@remix-run/node": patch | ||
"@remix-run/react": patch | ||
"@remix-run/serve": patch | ||
"@remix-run/server-runtime": patch | ||
"@remix-run/testing": patch | ||
--- | ||
|
||
Introduces the `defer()` API from `@remix-run/router` with support for server-rendering and HTTP streaming. This utility allows you to defer values returned from loaders by passing promises instead of resolved values. This has been refered to as "promise over the wire". | ||
|
||
Informational Resources: | ||
- https://gist.github.com/jacob-ebey/9bde9546c1aafaa6bc8c242054b1be26 | ||
- https://github.com/remix-run/remix/blob/main/decisions/0004-streaming-apis.md | ||
|
||
Documentation Resources (better docs specific to remix are in the works): | ||
- https://reactrouter.com/en/main/utils/defer | ||
- https://reactrouter.com/en/main/components/await | ||
- https://reactrouter.com/en/main/hooks/use-async-value | ||
- https://reactrouter.com/en/main/hooks/use-async-error |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { test, expect } from "@playwright/test"; | ||
|
||
import { createAppFixture, createFixture, js } from "./helpers/create-fixture"; | ||
import type { Fixture, AppFixture } from "./helpers/create-fixture"; | ||
import { PlaywrightFixture } from "./helpers/playwright-fixture"; | ||
|
||
let fixture: Fixture; | ||
let appFixture: AppFixture; | ||
|
||
test.beforeAll(async () => { | ||
fixture = await createFixture({ | ||
files: { | ||
"app/routes/index.jsx": js` | ||
import { useLoaderData, Link } from "@remix-run/react"; | ||
export default function Index() { | ||
return ( | ||
<div> | ||
<Link to="/redirect">Redirect</Link> | ||
<Link to="/direct-promise-access">Direct Promise Access</Link> | ||
</div> | ||
) | ||
} | ||
`, | ||
|
||
"app/routes/redirect.jsx": js` | ||
import { defer } from "@remix-run/node"; | ||
export function loader() { | ||
return defer({food: "pizza"}, { status: 301, headers: { Location: "/?redirected" } }); | ||
} | ||
export default function Redirect() {return null;} | ||
`, | ||
|
||
"app/routes/direct-promise-access.jsx": js` | ||
import * as React from "react"; | ||
import { defer } from "@remix-run/node"; | ||
import { useLoaderData, Link, Await } from "@remix-run/react"; | ||
export function loader() { | ||
return defer({ | ||
bar: new Promise(async (resolve, reject) => { | ||
resolve("hamburger"); | ||
}), | ||
}); | ||
} | ||
let count = 0; | ||
export default function Index() { | ||
let {bar} = useLoaderData(); | ||
React.useEffect(() => { | ||
let aborted = false; | ||
bar.then((data) => { | ||
if (aborted) return; | ||
document.getElementById("content").innerHTML = data + " " + (++count); | ||
document.getElementById("content").setAttribute("data-done", ""); | ||
}); | ||
return () => { | ||
aborted = true; | ||
}; | ||
}, [bar]); | ||
return ( | ||
<div id="content"> | ||
Waiting for client hydration.... | ||
</div> | ||
) | ||
} | ||
`, | ||
}, | ||
}); | ||
|
||
appFixture = await createAppFixture(fixture); | ||
}); | ||
|
||
test.afterAll(async () => appFixture.close()); | ||
|
||
test("deferred response can redirect on document request", async ({ page }) => { | ||
let app = new PlaywrightFixture(appFixture, page); | ||
await app.goto("/redirect"); | ||
await page.waitForURL(/\?redirected/); | ||
}); | ||
|
||
test("deferred response can redirect on transition", async ({ page }) => { | ||
let app = new PlaywrightFixture(appFixture, page); | ||
await app.goto("/"); | ||
await app.clickLink("/redirect"); | ||
await page.waitForURL(/\?redirected/); | ||
}); | ||
|
||
test("can directly access result from deferred promise on document request", async ({ | ||
page, | ||
}) => { | ||
let app = new PlaywrightFixture(appFixture, page); | ||
await app.goto("/direct-promise-access"); | ||
let element = await page.waitForSelector("[data-done]"); | ||
expect(await element.innerText()).toMatch("hamburger 1"); | ||
}); |
Oops, something went wrong.