Skip to content

Instantly share code, notes, and snippets.

@valin4tor
Last active February 15, 2020 19:24
Show Gist options
  • Save valin4tor/8583b4b0da14e408818e65c9a5d0b0df to your computer and use it in GitHub Desktop.
Save valin4tor/8583b4b0da14e408818e65c9a5d0b0df to your computer and use it in GitHub Desktop.
usePromise React Hook
import { useEffect } from "react";
const promiseMap = new WeakMap();
function usePromise(promise) {
let data = {};
if (promiseMap.has(promise)) {
data = promiseMap.get(promise);
} else {
promiseMap.set(promise, data);
}
useEffect(() => {
// cleanup: free map memory
return () => {
promiseMap.delete(promise);
};
}, [promise]);
data.status = data.status ?? "pending";
if (data.status === "pending") {
data.suspender =
data.suspender ??
promise
.then(result => {
data.status = "success";
data.result = result;
})
.catch(error => {
data.status = "error";
data.result = error;
});
throw data.suspender;
}
if (data.status === "error") {
throw data.result;
}
return data.result;
}
export default usePromise;
@valin4tor
Copy link
Author

Combine this with a Suspense fallback and define a promise outside of your component to wait until that promise is resolved. E.g.:

const titlePromise = getTitleAsync();

function Title() {
  const title = usePromise(titlePromise);
  return <h1>{title}</h1>;
}

function App() {
  return (
    <Suspense fallback={<h1>Loading...</h1>}>
      <Title />
    </Suspense>
  );
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment