如何使用钩子通过一个事件处理函数动态更新任何输入字段的值

IT技术 reactjs react-hooks controlled-component
2021-05-24 15:49:25

TL; 博士

有什么方法可以像使用有状态组件那样使用一个事件处理函数动态更新输入字段的值。

我正在处理一个包含 2 个字段的登录表单。电子邮件和密码。当我使用 2 个 useState 代表两个字段时,当我使用 handleChange 更新状态时,两个状态都会更新。这不是本意。

   const [email, setEmail] = useState()
   const [password, setPassword] = useState()

    const handleChange = e => {
        const {value} = e.target
        setEmail(value)
        setPassword(value)
    }

我不想使用多个事件处理程序来处理每个输入字段。我试过这个

    const [state , setState] = useState({
        email : "",
        password : ""
    })

    const handleChange = e => {
        const {name , value} = e.target
        setState({
            [name] : value
        })
    }

但这一次更新一个属性。并且其他财产value丢失。那么有什么方法可以像我们可以使用有状态组件那样使用一个事件处理函数更新我的所有输入字段。

    this.state = {
      email : "",
      password : ""
    }

    const handleChange = e => {
        const {name , value} = e.target
        this.setState({
           [name] : value
        })
    }
4个回答

感谢 DoğancanArabacı。我试图从基于类的组件中模仿 state 和 setState,所以感觉不会改变。我的解决方案看起来像这样。

const [state , setState] = useState({
    email : "",
    password : ""
})

const handleChange = e => {
    const {name , value} = e.target
    setState( prevState => ({
        ...prevState,
        [name] : value
    }))
}

您应该将 setState 与回调函数一起使用:

setState(prev => ({ 
    ...prev,
    email: 'new mail',
}))

您将创建一个新的 state 对象,该对象由以前的 state 创建。你可以覆盖任何你需要的东西。如果您有一个复杂的状态对象,则需要更多的新对象。

你可以像这样创建一个自定义钩子:

import { useState } from 'react';

export const useForm = (initialValues) => {
  const [values, setValues] = useState(initialValues);

  return {
    values,
    handleChange: (e) => {
      setValues({
        ...values,
        [e.target.name]: e.target.value,
      });
    },
    reset: () => setValues(initialValues),
  };
};

然后以任何形式使用它(例如):

export default function SignInForm() {
    const { values, handleChange, reset } = useForm({ username: '', password: '' });

    const handleSubmit = e => {
        e.preventDefault();
        reset();
    };

    return (
        <form onSubmit={handleSubmit}>
            <input
                type='text'
                name='username'
                placeholder='Enter your username...'
                onChange={handleChange}
                value={values.username}
            />
            <input
                type='password'
                name='password'
                placeholder='Enter your password...'
                onChange={handleChange}
                value={values.password}
            />
            <button type='submit'>
                Sign In
            </button>
        </form>
    );
}
// The useState Hook is used in React,
const {obj, setObj} = useState({ // Initially a value of `{}` object type
  foo: {},
  bar: {}
})

const handle = event => {
  setObj({   // here `{}` is a new value of type object
    ...obj,  // So, first use the ... operator to get the prevState
    bar: { qux: {} } // then, update
  })
}