部分项目如下:
...
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的值时,出现以下错误。
警告:组件正在将文本类型的受控输入更改为不受控制。输入元素不应从受控切换到不受控制(反之亦然)。在组件的使用寿命中决定使用受控还是不受控制的输入元素。
注意:我在密码部分遇到相同的问题
答案 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')} />
)