Last active
December 31, 2022 00:46
-
-
Save jacob-ebey/cd9c1e385a86e6fe28aaa4c73fad74a8 to your computer and use it in GitHub Desktop.
A very naive implementation of React's use() hook
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
// A very naive implementation of React's use() hook you can copy and paste into your app today | |
// to use with solutions such as remix's experimental `defer()` feature. | |
function use<T>(useable: Promise<T> | T) { | |
if (typeof useable != "object" || !useable || !("then" in useable)) { | |
return useable; | |
} | |
let promise = useable as Promise<T> & { _data?: T; _error?: unknown }; | |
if ("_data" in promise) { | |
return promise._data!; | |
} | |
if ("_error" in promise) { | |
throw promise._error; | |
} | |
throw promise.then( | |
(data) => { | |
promise._data = data; | |
}, | |
(error: unknown) => { | |
promise._error = 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
import { defer } from "@remix-run/node"; | |
import { useLoaderData } from "@remix-run/react"; | |
import { Suspense } from "react"; | |
import { use } from "~/react-use"; | |
function delay<T = unknown>(value: T, ms: number) { | |
return new Promise<T>((resolve) => setTimeout(() => resolve(value), ms)); | |
} | |
export function loader() { | |
return defer({ | |
first: delay("first", 1000), | |
second: delay("second", 2000), | |
}); | |
} | |
function Message({ message }: { message: Promise<string> | string }) { | |
return <p>{use(message)}</p>; | |
} | |
export default function Index() { | |
const { first, second } = useLoaderData<typeof loader>(); | |
return ( | |
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}> | |
<h1>Welcome to Remix</h1> | |
<Suspense fallback={<p>loading first...</p>}> | |
<Message message={first} /> | |
</Suspense> | |
<Suspense fallback={<p>loading second...</p>}> | |
<Message message={second} /> | |
</Suspense> | |
</div> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment