I need to detect a loading when submitting a form.
Right now its weird why the state is always idle
. Did I miss something?
login.tsx
import { type ActionFunction, type ActionFunctionArgs, json } from "@remix-run/cloudflare";
import { Link, useActionData } from "@remix-run/react";
import { getValues } from "@shared/util/remix";
import { AuthForm, authValidate } from "../../feature/auth";
export const action: ActionFunction = async ({ request }: ActionFunctionArgs) => {
const formData = await request.formData();
const { _action, email } = getValues<{
_action: string;
email: string;
}>(formData);
if (_action === "magic-link") {
const errors = authValidate(email);
if (errors) {
return json({ ok: false, errors }, 400);
}
try {
const response = await fetch("https://jsonplaceholder.typicode.com/posts", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "foo",
body: "bar",
userId: 1,
}),
});
return json({ ok: true, response });
} catch (err) {
console.error(err);
return json({ ok: false }, 500);
}
}
if (_action === "google") {
console.log("HEY GOOGLE");
// handle google redirection here
return null;
}
return json({});
};
export default function LoginRoute() {
const actionData = useActionData<typeof action>();
return (
<>
<div className="flex flex-col space-y-2">
<h1 className="text-2xl font-semibold tracking-tight">
Welcome back!
</h1>
</div>
<AuthForm type="login" actionData={actionData} />
<p className="px-8 text-xs text-center text-muted-foreground">
Don't have an account?{" "}
<Link to="/signup" className="text-primary underline">
Let's create one!
</Link>
</p>
</>
);
}
AuthForm.tsx
export function AuthForm({ type, actionData }: AuthFormProps) {
const navigation = useNavigation();
const isSubmitting = navigation.state !== "idle";
return (
<Form method="post">
<div className="grid gap-6">
<Button
name="_action"
value="google"
variant="outline"
type="submit"
className="flex items-center gap-1.5"
>
<img
src="/google-icon.svg"
alt="google-icon"
aria-hidden="true"
height={20}
width={20}
/>
Google
</Button>
<div className="relative">
<div className="absolute inset-0 flex items-center">
<span className="w-full border-t" />
</div>
<div className="relative flex justify-center text-xs uppercase">
<span className="bg-background px-2 text-muted-foreground/65 font-light">
Or continue with
</span>
</div>
</div>
<div className="grid gap-2">
<div className="grid gap-1">
<Label className="sr-only" htmlFor="email">
Email
</Label>
<Input
id="email"
placeholder="Email address"
name="email"
type="email"
autoCapitalize="none"
autoComplete="email"
autoCorrect="off"
/>
{actionData?.errors?.email && (
<p className="text-xs font-light text-destructive">
{actionData.errors.email}
</p>
)}
</div>
<Button
className="mt-2"
name="_action"
value="magic-link"
type="submit"
disabled={isSubmitting}
>
{isSubmitting ? (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
) : null}
{type === "login" ? "Sign in with email" : "Sign up with email"}
</Button>
</div>
</div>
</Form>
);
}