1
- import React , { useEffect , useState } from 'react' ;
1
+ import React , { useEffect , useRef , useState } from 'react' ;
2
2
import { useTranslation } from 'react-i18next' ;
3
3
import { Form , Field } from 'react-final-form' ;
4
4
import { useDispatch } from 'react-redux' ;
@@ -15,91 +15,112 @@ function LoginForm() {
15
15
return dispatch ( validateAndLoginUser ( formProps ) ) ;
16
16
}
17
17
const [ showPassword , setShowPassword ] = useState ( false ) ;
18
- const [ formUpdateKey , setFormUpdateKey ] = useState ( false ) ;
18
+ const formRef = useRef ( null ) ;
19
19
20
20
const handleVisibility = ( ) => {
21
21
setShowPassword ( ! showPassword ) ;
22
22
} ;
23
23
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
+ } ) ;
25
37
} , [ i18n . language ] ) ;
26
38
27
39
return (
28
40
< Form
29
41
fields = { [ 'email' , 'password' ] }
30
42
validate = { validateLogin }
31
43
onSubmit = { onSubmit }
32
- key = { formUpdateKey }
33
44
>
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 >
66
62
< input
67
63
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"
72
69
{ ...field . input }
73
70
/>
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
+ ) }
86
112
</ 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 >
93
117
) }
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
+ } }
103
124
</ Form >
104
125
) ;
105
126
}
0 commit comments