When I fill my form fields separately they work fine. But when I try to use google auto fill option, the logging works, state update happens for each one of the fields it comes in the log, but the change does not persist from one update to another. How can I fix this? I needed validation on the go
This is my form input file.
import React, {FC, useCallback, useEffect, useState} from "react"
import './FormInput.css'
import { InputFieldParams } from "./interfaces"
import { ifFieldValueValid } from "./utils.ts"
interface FormInputProps {
inputField: InputFieldParams
setFieldValues: CallableFunction
}
const FormInput:FC<FormInputProps> = ({inputField, setFieldValues}) => {
const {labelName, fieldName, inputType} = inputField;
const [value, setValue] = useState();
const [valid, setValid] = useState<boolean>(false);
const handleFormInputChange = useCallback((e) => {
e.stopPropagation();
setValue(e.target.value)
setValid(ifFieldValueValid(e.target.value, fieldName))
},[value])
useEffect(() => {
const delayInputTimeout = setTimeout(() => {
console.log('value1', value)
console.log('valid1', valid)
setFieldValues(fieldName, value, valid)
}, 1000);
return () => clearTimeout(delayInputTimeout);
},[value, valid])
return (
<div className="FormInput">
<label>{labelName}</label>
<input type={inputType} value={value} name={labelName} onChange={handleFormInputChange}/>
</div>
)
}
export default FormInput
This is the hook I am using
import { useCallback, useEffect, useState } from "react";
import { InputFieldParams, FieldValue } from "./interfaces";
import { getFormValuesState } from "./utils.ts";
const inputFields: InputFieldParams[] = [
{id: 1, fieldName: 'username', labelName: 'Name', inputType: 'text', placeHolder: 'Name'},
{id: 2, fieldName: 'age' ,labelName: 'Age', inputType: 'number', placeHolder: '0'},
{id: 3, fieldName: 'dateOfBirth' ,labelName: 'DOB', inputType: 'text', placeHolder: 'DD/MM/YYYY'},
{id: 4, fieldName: 'email' ,labelName: 'Email', inputType: 'text', placeHolder: '[email protected]'},
{id: 5, fieldName: 'mobileNumber' ,labelName: 'Mobile Number', inputType: 'text', placeHolder: '9462501990'}
]
const checkIfAllValuesValid = (fieldValuesArray: FieldValue[]) => {
fieldValuesArray.forEach((fieldValue) => {
if(fieldValue.validated == false) {
return false;
}
})
return true;
}
export const useFormStateAndValidate = () => {
const [isSubmitValid, setIsSubmitValid] = useState(false);
const [formFieldValues, setFormFieldValues] = useState<FieldValue[]>(getFormValuesState(inputFields));
const setFieldValues = useCallback((fieldName: string, newValue: any, isValueValid: boolean) => {
let invalidFieldCount = 0;
const newFieldValueState: FieldValue[] = formFieldValues.map((prevStateFormField) => {
if(prevStateFormField.fieldName == fieldName) {
if(!isValueValid) invalidFieldCount++
return {...prevStateFormField, value: newValue, validated: isValueValid}
} else {
if(!prevStateFormField.validated) invalidFieldCount++;
return prevStateFormField
}
})
setFormFieldValues(newFieldValueState)
console.log(newFieldValueState)
console.log(invalidFieldCount)
if(invalidFieldCount > 0) setIsSubmitValid(false);
else setIsSubmitValid(true)
}, [formFieldValues])
return {
inputFields: inputFields,
isSubmitValid: isSubmitValid,
setFieldValues: setFieldValues,
}
}
this is the main file where form renders.
import React, { useCallback, useState } from "react";
import './MyForm.css'
import FormInput from "./FormInput.tsx"
import { useFormStateAndValidate } from "./hooks.tsx";
const MyForm = () => {
const {isSubmitValid, inputFields, setFieldValues} = useFormStateAndValidate();
return (
<div className="MainFormContainer">
<div className="CustomForm">
<h2 className="FormHeading">Fill the deatils and then submit</h2>
<div className="FormInputs">
{inputFields.map((field, index) => {
return (
<FormInput
key={`field_${index}`}
inputField={field}
setFieldValues={setFieldValues}
/>
)
})}
</div>
<div className="SubmitButton">
<button disabled={!isSubmitValid}>SUBMIT</button>
</div>
</div>
</div>
)
}
export default MyForm