这是我的代码,
const [state, setState] = useState({
email: '',
password: '',
last_name: '',
first_name: ''
});
const emailChangeHandler = (e) => {
setState(c => {
return {
...c,
email: e.target.value
}
})
}
return (
<form>
<input className="input" type="text" name="email" onChange={emailChangeHandler}/>
<input className="input" type="text"/>
<input className="input" type="text"/>
</form>
)
当输入值更改时,我正在尝试更新状态。
但是错误“ TypeError:无法读取null的属性'value'”,
13 | setState(c => {
14 | return {
15 | ...c,
> 16 | email: e.target.value
17 | ^ }
18 | })
19 | }
因此,我正在尝试不使用当前状态更新状态,如下所示:
const emailChangeHandler = (e) => {
setState({...state, email: e.target.value})
}
及其工作,但是为什么呢? 带有currentstate和不带有currentstate的setstate有什么区别?
答案 0 :(得分:1)
如果使用setState回调,则在事件之前通过react清除事件值。因此,您需要在使用前存储值
const email = e.target.value;
setState(c => {
return {
...c,
email,
}
})
就回调和不带callbcak的区别而言, 状态更新是批量处理的,因此您可以使用功能性setState,即具有回调功能的setState,即使在同一事件处理程序中进行了多个setState调用,也保证值将来自先前的更新
例如
const emailChangeHandler = (e) => {
setState({
...c,
email: [...c.email,e.target.value]
})
setState({
...c,
email: [...c.email, 'psw']
})
}
在上述情况下,如果c
是{email: ['xyz@g.com'], name: 'p'}
,则发布更新后的值将变为{email: ['xyz@g.com', 'psw'], name: 'p'}
而不是{email: ['xyz@g.com', e.target.value, 'psw'], name: 'p'}
答案 1 :(得分:0)
This will work:
const emailChangeHandler = (e) => {
const value = event.target.value;
setState(c => {
return {
...c,
email: value
}
})
}
因此,这里我们尝试在闭包中使用e.target.value
,并且闭包基本上将event object
锁定为后续按键。
关于React Events:
反应事件是特殊的合成事件,可复制本地dom事件
React基本上会重用这些事件对象,在我们的案例中,它也会重用先前的事件对象,因此我们面临着问题。