Skip to content

Commit d8bf879

Browse files
imporved:user touched values are persisited while translating the errors
1 parent 8117fdb commit d8bf879

File tree

2 files changed

+224
-189
lines changed

2 files changed

+224
-189
lines changed

client/modules/User/components/LoginForm.jsx

Lines changed: 88 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { useEffect, useRef, useState } from 'react';
22
import { useTranslation } from 'react-i18next';
33
import { Form, Field } from 'react-final-form';
44
import { useDispatch } from 'react-redux';
@@ -15,91 +15,112 @@ function LoginForm() {
1515
return dispatch(validateAndLoginUser(formProps));
1616
}
1717
const [showPassword, setShowPassword] = useState(false);
18-
const [formUpdateKey, setFormUpdateKey] = useState(false);
18+
const formRef = useRef(null);
1919

2020
const handleVisibility = () => {
2121
setShowPassword(!showPassword);
2222
};
2323
useEffect(() => {
24-
setFormUpdateKey(!formUpdateKey);
24+
const form = formRef.current;
25+
if (!form) return;
26+
27+
const { values } = form.getState(); // store current form touched values
28+
form.reset();
29+
30+
// Restore prev form values and trigger validation
31+
Object.keys(values).forEach((field) => {
32+
if (values[field]) {
33+
// Only reapply touched values
34+
form.change(field, values[field]);
35+
}
36+
});
2537
}, [i18n.language]);
2638

2739
return (
2840
<Form
2941
fields={['email', 'password']}
3042
validate={validateLogin}
3143
onSubmit={onSubmit}
32-
key={formUpdateKey}
3344
>
34-
{({ handleSubmit, submitError, submitting, modifiedSinceLastSubmit }) => (
35-
<form className="form" onSubmit={handleSubmit}>
36-
<Field name="email">
37-
{(field) => (
38-
<div className="form__field">
39-
<label htmlFor="email" className="form__label">
40-
{t('LoginForm.UsernameOrEmail')}
41-
</label>
42-
<input
43-
className="form__input"
44-
aria-label={t('LoginForm.UsernameOrEmailARIA')}
45-
type="text"
46-
id="email"
47-
autoComplete="username"
48-
autoCapitalize="none"
49-
{...field.input}
50-
/>
51-
{field.meta.touched && field.meta.error && (
52-
<span className="form-error" aria-live="polite">
53-
{field.meta.error}
54-
</span>
55-
)}
56-
</div>
57-
)}
58-
</Field>
59-
<Field name="password">
60-
{(field) => (
61-
<div className="form__field">
62-
<label htmlFor="password" className="form__label">
63-
{t('LoginForm.Password')}
64-
</label>
65-
<div className="form__field__password">
45+
{({
46+
handleSubmit,
47+
submitError,
48+
submitting,
49+
modifiedSinceLastSubmit,
50+
form
51+
}) => {
52+
formRef.current = form;
53+
54+
return (
55+
<form className="form" onSubmit={handleSubmit}>
56+
<Field name="email">
57+
{(field) => (
58+
<div className="form__field">
59+
<label htmlFor="email" className="form__label">
60+
{t('LoginForm.UsernameOrEmail')}
61+
</label>
6662
<input
6763
className="form__input"
68-
aria-label={t('LoginForm.PasswordARIA')}
69-
type={showPassword ? 'text' : 'password'}
70-
id="password"
71-
autoComplete="current-password"
64+
aria-label={t('LoginForm.UsernameOrEmailARIA')}
65+
type="text"
66+
id="email"
67+
autoComplete="username"
68+
autoCapitalize="none"
7269
{...field.input}
7370
/>
74-
<button
75-
className="form__eye__icon"
76-
type="button"
77-
onClick={handleVisibility}
78-
aria-hidden="true"
79-
>
80-
{showPassword ? (
81-
<AiOutlineEyeInvisible />
82-
) : (
83-
<AiOutlineEye />
84-
)}
85-
</button>
71+
{field.meta.touched && field.meta.error && (
72+
<span className="form-error" aria-live="polite">
73+
{field.meta.error}
74+
</span>
75+
)}
76+
</div>
77+
)}
78+
</Field>
79+
<Field name="password">
80+
{(field) => (
81+
<div className="form__field">
82+
<label htmlFor="password" className="form__label">
83+
{t('LoginForm.Password')}
84+
</label>
85+
<div className="form__field__password">
86+
<input
87+
className="form__input"
88+
aria-label={t('LoginForm.PasswordARIA')}
89+
type={showPassword ? 'text' : 'password'}
90+
id="password"
91+
autoComplete="current-password"
92+
{...field.input}
93+
/>
94+
<button
95+
className="form__eye__icon"
96+
type="button"
97+
onClick={handleVisibility}
98+
aria-hidden="true"
99+
>
100+
{showPassword ? (
101+
<AiOutlineEyeInvisible />
102+
) : (
103+
<AiOutlineEye />
104+
)}
105+
</button>
106+
</div>
107+
{field.meta.touched && field.meta.error && (
108+
<span className="form-error" aria-live="polite">
109+
{field.meta.error}
110+
</span>
111+
)}
86112
</div>
87-
{field.meta.touched && field.meta.error && (
88-
<span className="form-error" aria-live="polite">
89-
{field.meta.error}
90-
</span>
91-
)}
92-
</div>
113+
)}
114+
</Field>
115+
{submitError && !modifiedSinceLastSubmit && (
116+
<span className="form-error">{submitError}</span>
93117
)}
94-
</Field>
95-
{submitError && !modifiedSinceLastSubmit && (
96-
<span className="form-error">{submitError}</span>
97-
)}
98-
<Button type="submit" disabled={submitting}>
99-
{t('LoginForm.Submit')}
100-
</Button>
101-
</form>
102-
)}
118+
<Button type="submit" disabled={submitting}>
119+
{t('LoginForm.Submit')}
120+
</Button>
121+
</form>
122+
);
123+
}}
103124
</Form>
104125
);
105126
}

0 commit comments

Comments
 (0)