hema sundar Ginni
hema sundar Ginni

Reputation: 323

React |How to Update parent state when multiple children sending event to parent at same time

I have Form and Input components. Form contains Input as children. whenever the form submits I am sending an incremented value to child Input component. In the Input component, I have a listener (useEffect) on that incremented value to validate the input. after validating the input I am calling a function onValidation(isValid) which is received from parent as props. and trying to update the parent component with validation results. But, When the form is submitting all the child components are calling the onValidation method same time and parent setting the state immediately. because the react setstate won't affect immediately the validation data is not setting correctly in parent. Here is the code.

Is there any way to solve this problem? If not, what is the best pattern for these use cases?


function Form() {
    const [validations,setValidations] = useState({})

    function onValidation(isValid,key) {
        setValidations({...validations,...{[key]:isValid}});
    }

    function onSubmit(){
        //Here the validations object not containing all the input fields data.
        // because while doing setValidation some data is missing
        let isValid = Object.keys(validations).reduce((prev,curKey)=>{return (prev && validations[curKey]) },true);
        if(isValid) {
            window.alert("The form is valid");
        }else {
            window.alert("The form is not valid");
        }
    }

    return (
        <form onSubmit={onSubmit}>
            <Input name="first" onValidation={onValidation}/>
            <Input name="second" onValidation={onValidation}/>
            <Input name="third" onValidation={onValidation}/>
            <Input name="fourth" onValidation={onValidation}/>
        </form>
    )
}

function Input(value,name,onValidation) {
    function validate(e) {
        var val = e.target.value;
        if(val){
            onValidation(true,name)
        }else {
            onValidation(false,name)
        }
    }

    return (
        <input type="text" onChange={validate} value={value}>
    )
}

Upvotes: 0

Views: 1212

Answers (2)

Eliav Louski
Eliav Louski

Reputation: 5264

just add initial state to validations. https://codesandbox.io/s/cocky-snowflake-g2rr5?file=/src/App.js

your initial keys is empty object so none of the props are false therefore validation is ok

update

I now understand what's annoying you. please read this answer.

Upvotes: 0

hema sundar Ginni
hema sundar Ginni

Reputation: 323

After little digging found a solution for this problem.

https://reactjs.org/docs/faq-state.html#what-is-the-difference-between-passing-an-object-or-a-function-in-setstate

when setting the validations with setValidations, instead of setting it directly we have to set it with a callback function. with this way the state is setting properly. updated the code sandbox accordingly.

    setValidations((validations) => {
      return { ...validations, ...{ [key]: isValid } };
    });

https://codesandbox.io/s/serene-hofstadter-4nqr3?file=/src/App.js

Upvotes: 1

Related Questions