1- import React , { useEffect , useState } from 'react' ;
1+ import React , { useEffect , useRef , useState } from 'react' ;
22import { useTranslation } from 'react-i18next' ;
33import { Form , Field } from 'react-final-form' ;
44import { 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