我正在尝试构建一个组件,该组件将自动检查输入字段中的有效电子邮件地址,然后使用setState
将其添加到数组中。
我的那部分工作正常,但是当您在空白字段上退格时,我也希望它删除最后一项。
我遇到的问题是,当我拼接数组中的最后一项并使用setState
更新它时,它不呈现新的数组值吗?
如果将值记录在onKeyDown
调用的函数中,它将记录正确的更新数组值this.state.emails
。但是,渲染功能会记录旧值,并且列表不会更新。
Codepen:https://codepen.io/adamcoulombe/pen/zJxoER
class MultiEmailInput extends React.Component {
constructor(props) {
super(props)
this.state = {
emails:[]
};
}
fieldChange(e){
if (e.target.value !== ''){
if (this.validateEmail(e.target.value)===true){
this.setState({emails: this.state.emails.concat(e.target.value)});
}
}
}
fieldKeyDown(e){
// console.log(e.target.value);
if(e.target.value===''){
var key = e.keyCode || e.charCode;
if (key == 8 || key == 46) {
this.setState({ emails: this.state.emails.splice(-1) });
//logs correct updated value
console.log(this.state.emails);
}
}
}
validateEmail(email) {
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(String(email).toLowerCase());
}
render() {
//this value doesnt get updated?
console.log(this.state.emails);
return (
<div className={"email-multi-input"+this.props.className}>
<ul className="added-emails" ref="email-multi-input-added-emails">
{
this.state.emails.map((email, i) => {
return (<li key={i}>{email}</li>)
})}
</ul>
<input ref="email-multi-input-field" onChange={this.fieldChange.bind(this)} onKeyDown={this.fieldKeyDown.bind(this)} />
</div>
);
}
}
React.render(
<MultiEmailInput />,
document.body
);
答案 0 :(得分:4)
问题出在fieldKeyDown
中的这一行:
this.setState({ emails: this.state.emails.splice(-1) });
splice
方法使数组this.state.emails
突变并删除最后一个元素,但是它返回。因此上方的那行将this.state.emails
设置为等于this.state.emails
的最后一个元素。
在console.log(this.state.emails)
中调用fieldKeyDown
时看到正确值的原因是,由于React不会立即更新状态,所以this.setState
的影响尚未发生(请参见{{ 3}})。因此,您正在查看已被突变的旧this.state.emails
。当您在console.log
中render
时会看到新值,因为render
在状态更新后被调用。
请注意:您State Updates May Be Asynchronous(即使用splice
)应该只使用setState
来更改状态。对于此问题,您可以将this.state.emails
设置为等于slice
的{{1}}。这是一个示例:
this.state.emails