Autofill forms not updating react state (formValues)

38 Views Asked by At

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
0

There are 0 best solutions below