Im trying to create a form with React. This form uses a custom Input component I created various times. In the parent form Im trying to get a complete object with all names and all values of the form:
{inputName: value, inputName2: value2, inputName3: value3}
For this, I created a ‘component updated’ hook, that calls the function property onNewValue
to send the new value to the parent (two way data binding):
useEffect(() => { if (onNewValue) onNewValue({ name, value }); }, [value]);
The parent form receives the data in the handleInputChange
function:
export default () => { const [values, setValues] = useState({}); const handleInputChange = ({ name, value }: { name: string; value: string | number; }): void => { console.log("handleInputChange", { name, value }); // All elements are logged here successfully setValues({ ...values, [name]: value }); }; return ( <> <form> <Input name={"nombre"} required={true} label={"Nombre"} maxLength={30} onNewValue={handleInputChange} /> <Input name={"apellidos"} required={true} label={"Apellidos"} maxLength={60} onNewValue={handleInputChange} /> <Input name={"telefono"} required={true} label={"Teléfono"} maxLength={15} onNewValue={handleInputChange} /> <Input name={"codigoPostal"} required={true} label={"Código Postal"} maxLength={5} onNewValue={handleInputChange} type={"number"} /> </form> State of values: {JSON.stringify(values)} </> ); };
This way all elements from all inputs should be set on init:
{"codigoPostal":"","telefono":"","apellidos":"","nombre":""}
But for some reason only the last one is being set:
{"codigoPostal":""}
You can find the bug here: https://codesandbox.io/s/react-typescript-vx5py
Thanks!
Advertisement
Answer
The set state process in React is an asynchronous process. Therefore even if the function is called, values
has not updated the previous state just yet.
To fix, this you can use the functional version of setState
which returns the previous state as it’s first argument.
setValues(values=>({ ...values, [name]: value }));