[英]React not rendering with correct state value after using this.setState
I am trying to build a component that automatically checks an input field for a valid email address, then adds it to an array using setState
. 我正在尝试构建一个组件,该组件将自动检查输入字段中的有效电子邮件地址,然后使用
setState
将其添加到数组中。
I have that part working correctly, but I also want it to remove the last item when you backspace on the empty field. 我的那部分工作正常,但是当您在空白字段上退格时,我也希望它删除最后一项。
The problem I am having is that when I splice the last item in the array, and update it using setState
, it doesnt render the new array value? 我遇到的问题是,当我拼接数组中的最后一项,并使用
setState
更新它时,它不会呈现新的数组值吗?
If I log the value in the function called by onKeyDown
, it logs the correct updated array value of this.state.emails
. 如果将值记录在
onKeyDown
调用的函数中,它将记录this.state.emails
的正确更新数组值。 The render function however logs the old value and the list doesnt update. 但是,渲染功能会记录旧值,并且列表不会更新。
Codepen: https://codepen.io/adamcoulombe/pen/zJxoER 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
);
The problem is with this line in fieldKeyDown
: 问题出在
fieldKeyDown
这一行:
this.setState({ emails: this.state.emails.splice(-1) });
the splice
method mutates the array this.state.emails
and removes the last element, however it returns that last element. splice
方法this.state.emails
数组并删除了最后一个元素,但是它返回了最后一个元素。 So that line above sets this.state.emails
equal to the last element of this.state.emails
. 因此,上述套该行
this.state.emails
等于最后一个元素this.state.emails
。
The reason you see the correct value when you call console.log(this.state.emails)
in fieldKeyDown
is because the effect of this.setState
has not taken place yet since React does not update state immediately (See State Updates May Be Asynchronous ). 在
fieldKeyDown
调用console.log(this.state.emails)
时看到正确值的原因是,由于React不会立即更新状态,因此this.setState
的影响尚未发生(请参阅状态更新可能是异步的 ) 。 So you are looking at the old this.state.emails
, which has been mutated. 因此,您正在查看已
this.state.emails
的旧this.state.emails
。 When you console.log
in render
you see the new value because render
is called after state has been updated. 当您在
render
console.log
,您会看到新值,因为在状态更新后调用了render
。
An additional note: You should not mutate state directly (ie using splice
) instead you should only change state using setState
. 补充说明:您不应直接更改状态(即使用
splice
),而应仅使用setState
更改状态。 For this problem you can set this.state.emails
equal to a slice
of this.state.emails
. 对于这个问题,你可以设置
this.state.emails
等于slice
的this.state.emails
。 Here's an example: 这是一个例子:
this.setState({ emails: this.state.emails.slice(0, -1) });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.