I have critical data and noncritical data. Both are provided through the loader. I want to transmit the noncritical data as a promise using defer.
Given the following example, I would expect "quickAndCritical" to be rendered after about 1s and "slow" about 2s later. But actually the page stays blank for about 3s and then renders both.
Am I making a mistake here? I would appreciate any help!
import React, { Suspense } from "react";
import { defer } from "@remix-run/node";
import { Await, Links, Meta, useLoaderData } from "@remix-run/react";
import type { LoaderFunction, LoaderFunctionArgs } from "@remix-run/node";
export function quickAndCritical() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("quickAndCritical");
}, 1000);
});
}
export function slowAndDeferrable() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("slow");
}, 3000);
});
}
export const loader: LoaderFunction = async ({ request }: LoaderFunctionArgs) => {
const critical = await quickAndCritical();
const canBeDeferred = slowAndDeferrable();
return defer({
critical,
canBeDeferred,
});
};
export default function App() {
const { critical, canBeDeferred } = useLoaderData();
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<Meta />
<Links />
</head>
<body>
{critical}
<br></br>
<br></br>
<Suspense fallback={null}>
<Await resolve={canBeDeferred}>{(resolvedData) => <div>{resolvedData}</div>}</Await>
</Suspense>
</body>
</html>
);
}
According to the Remix Docs, you need to initiate promises for deferred data before you await any other promises.
Swapping lines 1 & 2 should do the trick for ya.