setState仅在将对象用作状态时设置最后输入

时间:2019-10-11 16:30:05

标签: javascript reactjs typescript react-hooks

我正在尝试使用React创建一个表单。该表单使用了我多次创建的自定义输入组件。在父表单中,我试图获取具有表单的所有名称和所有值的完整对象:

  {inputName: value, inputName2: value2, inputName3: value3}

为此,我创建了一个“组件更新”钩子,该钩子调用函数属性onNewValue来将新值发送到父级(双向数据绑定):

  useEffect(() => {
    if (onNewValue) onNewValue({ name, value });
  }, [value]);

父表单通过handleInputChange函数接收数据:

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)}
    </>
  );
};

通过这种方式,所有输入中的所有元素都应设置为init :

  {"codigoPostal":"","telefono":"","apellidos":"","nombre":""}

但是由于某些原因仅设置了最后一个

  {"codigoPostal":""}

您可以在此处找到错误: https://codesandbox.io/s/react-typescript-vx5py

谢谢!

4 个答案:

答案 0 :(得分:1)

useState()不会像类中的this.setState()那样合并状态。

因此最好将这些字段分成各个状态。

const [nombre, setNombre] = useState("")
const [apellidos, setApellidos] = useState("")
// and so on

更新

鉴于setValue()在初始化期间处于异步使用先前状态。

setValues((prevState) => ({ ...prevState, [name]: value }));

答案 1 :(得分:0)

更新后的固定代码,请查看:

https://codesandbox.io/s/react-typescript-mm7by

看看:

  const handleInputChange = ({
    name,
    value
  }: {
    name: string;
    value: string | number;
  }): void => {
    console.log("handleInputChange", { name, value });
    setValues(prevState => ({ ...prevState, [name]: value }));
  };

答案 2 :(得分:0)

React中的设置状态过程是一个异步过程。因此,即使调用了该函数,values仍未更新以前的状态。

要解决此问题,您可以使用setState的功能版本,该功能版本返回先前的状态作为其第一个参数。

setValues(values=>({ ...values, [name]: value }));

答案 3 :(得分:0)

 const [ list, setList ] = useState( [ ] );

正确:

 setList ( ( list ) => [ ...list, value ] )

避免使用:

 setList( [ ...list, value ] )