Skip to content

Instantly share code, notes, and snippets.

@kiliman
Created February 7, 2023 21:31
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kiliman/c900df084ea7dd306e0cb85b81848fbb to your computer and use it in GitHub Desktop.
Save kiliman/c900df084ea7dd306e0cb85b81848fbb to your computer and use it in GitHub Desktop.
Remix `useSubmitPromise` hook
import type { ActionArgs, LoaderArgs } from "@remix-run/node";
import { json } from "@remix-run/node";
import type { SubmitOptions } from "@remix-run/react";
import { useActionData, useNavigation, useSubmit } from "@remix-run/react";
import { useCallback, useEffect, useMemo } from "react";
export function loader({ request }: LoaderArgs) {
return json({ message: "Hello World" });
}
export function action({ request }: ActionArgs) {
return json({ message: "Goodbye World" });
}
export default function Index() {
const submit = useSubmitPromise();
const doSubmit = useCallback(
(e: any) => {
console.log("doSubmit");
e.preventDefault();
submit({ test: "123" }, { method: "post", action: "?index" }).then(
(data) => {
console.log("result", data);
}
);
},
[submit]
);
return (
<div>
<h1>Welcome to Remix</h1>
<button onClick={doSubmit}>useSubmitPromise</button>
</div>
);
}
// remix doesn't export this type
declare type SubmitTarget =
| HTMLFormElement
| HTMLButtonElement
| HTMLInputElement
| FormData
| URLSearchParams
| {
[name: string]: string;
}
| null;
function useSubmitPromise() {
const submit = useSubmit();
const navigation = useNavigation();
const actionData = useActionData();
const $deferred = useMemo(() => deferred(), []);
useEffect(() => {
if (navigation.state === "idle" && actionData) {
$deferred.resolve(actionData);
}
}, [$deferred, navigation.state, actionData]);
const _submit = useCallback(
(target: SubmitTarget, options: SubmitOptions = {}) => {
submit(target, options);
return $deferred.promise;
},
[$deferred.promise, submit]
);
return _submit;
}
// create a *deferred* promise
function deferred() {
let resolve: any;
let reject: any;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
return { resolve, reject, promise };
}
@kiliman
Copy link
Author

kiliman commented Feb 7, 2023

Sample app on ⚡️StackBlitz
https://stackblitz.com/edit/node-crfv2p

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