Skip to content
Advertisement

setState only setting last input when using object as state

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 }));
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement