我无法更改输入中的值

时间:2019-11-10 08:43:03

标签: javascript reactjs react-redux react-router dom-events

部分项目如下:

...
const INITIAL_STATE = {
  email: '',
  password: '',
  error: null
}

const SignInPage = () => {
  return(
    <div>
      <h2>Sign In</h2>
      <SignInForm/>
      <SignUpLink/>
    </div>
  )
}

const SignInFormBase = props => {
  const[init,setInit] = useState(INITIAL_STATE);
  const onSubmit = () => {

  }
  const onChange = (event) => {
    setInit({
      [event.target.name]: event.target.value
    })    
  }
  const isInvalid = init.password === '' || init.email === '';
  return(
    <form onSubmit={onSubmit}>
      <input
        name='email'
        value={init.email}
        onChange={onChange}
        type='text'
        placeholder='Email Address'
      />
      <input
        ...
      />
      <button disabled={isInvalid} type='submit'>Sign In</button>
      {init.error && <p>{init.error.message}</p>}
    </form>
  )
}

const SignInForm = compose(
  withRouter,
  withFirebase
)(SignInFormBase)
export default SignInPage;
export {SignInForm}

问题是: 当我在onChange函数中用setInit替换init的值时,出现以下错误。

  

警告:组件正在将文本类型的受控输入更改为不受控制。输入元素不应从受控切换到不受控制(反之亦然)。在组件的使用寿命中决定使用受控还是不受控制的输入元素。

注意:我在密码部分遇到相同的问题

1 个答案:

答案 0 :(得分:1)

您剥离了部分代码,但我认为您没有足够好的阅读react hooks文档。通过使用钩子,您将无法替换先前合并值的setState。因此,当您致电

setInit({
   [event.target.name]: event.target.value
})

您将用新对象替换整个init变量,因此其他字段将指向未定义的值,并且反应会将组件更改为不受控制,然后在输入值时再次更改为受控制。如果要保持对象处于状态,则需要自己进行合并。最简单的方法是将对象散布用作

  setInit({
    ...init, // <- spread old state
    [event.target.name]: event.target.value
  })

使用此代码,旧状态将保留在输入之间。我还建议您不要从字段名称推断状态属性,因为稍后您可以轻松引入可以创建咖喱全局onChange的错误

const onChange = (field) => (event) => {
  setInit({
   ...init,
   [field]: event.target.value
  })
}

return (
  <input onChange={onChange('name')} />
)