我正在尝试构建一个组件,自动检查输入字段中的有效电子邮件地址,然后使用 setState
将其添加到数组中。
我的那部分工作正常,但我也希望它在您在空白字段上退格时删除最后一项。
我遇到的问题是,当我拼接数组中的最后一项并使用 setState
更新它时,它不会呈现新的数组值?
如果我在 onKeyDown
调用的函数中记录值,它会记录 this.state.emails
的正确更新数组值。然而,渲染函数会记录旧值并且列表不会更新。
代码笔: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
);
最佳答案
问题出在 fieldKeyDown
中的这一行:
this.setState({ emails: this.state.emails.splice(-1) });
splice
方法改变数组 this.state.emails
并删除最后一个元素,但是它返回最后一个元素。所以上面那行设置 this.state.emails
等于 this.state.emails
的最后一个元素。
在 fieldKeyDown
中调用 console.log(this.state.emails)
时看到正确值的原因是 this.setState 的作用
尚未发生,因为 React 不会立即更新状态(参见 State Updates May Be Asynchronous)。所以你正在查看旧的 this.state.emails
,它已经发生了变异。当您在 render
中使用 console.log
时,您会看到新值,因为 render
在状态更新后被调用。
附加说明:您 should not mutate state directly (即使用 splice
),您应该只使用 setState
更改状态。对于这个问题,您可以将 this.state.emails
设置为等于 this.state.emails
的 slice
。这是一个例子:
this.setState({ emails: this.state.emails.slice(0, -1) });
关于javascript - 使用 this.setState 后 react 不呈现正确的状态值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51953950/