Fix login page CTA disabled state (#2832)

* fix(ui/login): better disabled state for login CTA

The fix involves tracking the form submission with a dedicated state `submitInProgress` with React.
`formState` from `react-hook-form` does not take time taken for the network call into account. For example,
if the api takes 5 seconds to complete, we would expect the `formState.isSubmitting` to be true for `5`
seconds. But, surprisingly this is not the case and `formState` from `react-hook-form` resolves
immediately after it makes a successful connection to the endpoint.

A dedicated state (with `useState`) is introduced that is enabled when the user clicks on the login CTA, and disabled when the api call is resolved, either successfully or with an error.

* Update login.tsx

* Update login.tsx

* Fixes isSubmitting state

Co-authored-by: zomars <zomars@me.com>
This commit is contained in:
Arun Kumar
2022-05-23 22:50:35 +05:30
committed by GitHub
parent 53a7b1cc37
commit 7d7a1c5bbc

View File

@@ -45,6 +45,8 @@ export default function Login({
const { t } = useLocale();
const router = useRouter();
const form = useForm<LoginValues>();
const { formState } = form;
const { isSubmitting } = formState;
const [twoFactorRequired, setTwoFactorRequired] = useState(false);
const [errorMessage, setErrorMessage] = useState<string | null>(null);
@@ -97,26 +99,27 @@ export default function Login({
<AuthContainer
title={t("login")}
description={t("login")}
loading={form.formState.isSubmitting}
showLogo
heading={twoFactorRequired ? t("2fa_code") : t("sign_in_account")}
footerText={twoFactorRequired ? TwoFactorFooter : LoginFooter}>
<Form
form={form}
className="space-y-6"
handleSubmit={(values) => {
handleSubmit={async (values) => {
setErrorMessage(null);
telemetry.withJitsu((jitsu) => jitsu.track(telemetryEventTypes.login, collectPageParameters()));
signIn<"credentials">("credentials", { ...values, callbackUrl, redirect: false })
.then((res) => {
if (!res) setErrorMessage(errorMessages[ErrorCode.InternalServerError]);
// we're logged in! let's do a hard refresh to the desired url
else if (!res.error) router.push(callbackUrl);
// reveal two factor input if required
else if (res.error === ErrorCode.SecondFactorRequired) setTwoFactorRequired(true);
// fallback if error not found
else setErrorMessage(errorMessages[res.error] || t("something_went_wrong"));
})
.catch(() => setErrorMessage(errorMessages[ErrorCode.InternalServerError]));
const res = await signIn<"credentials">("credentials", {
...values,
callbackUrl,
redirect: false,
});
if (!res) setErrorMessage(errorMessages[ErrorCode.InternalServerError]);
// we're logged in! let's do a hard refresh to the desired url
else if (!res.error) router.push(callbackUrl);
// reveal two factor input if required
else if (res.error === ErrorCode.SecondFactorRequired) setTwoFactorRequired(true);
// fallback if error not found
else setErrorMessage(errorMessages[res.error] || t("something_went_wrong"));
}}
data-testid="login-form">
<div>
@@ -157,13 +160,7 @@ export default function Login({
{errorMessage && <Alert severity="error" title={errorMessage} />}
<div className="flex space-y-2">
<Button
className="flex w-full justify-center"
type="submit"
disabled={
form.formState.isSubmitting ||
(form.formState.isSubmitted && !twoFactorRequired && !errorMessage)
}>
<Button className="flex w-full justify-center" type="submit" disabled={isSubmitting}>
{twoFactorRequired ? t("submit") : t("sign_in")}
</Button>
</div>