使用this.setState后反应不渲染具有正确的状态值

时间:2018-08-21 17:34:10

标签: javascript reactjs

我正在尝试构建一个组件,该组件将自动检查输入字段中的有效电子邮件地址,然后使用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
);

1 个答案:

答案 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.logrender时会看到新值,因为render在状态更新后被调用。

请注意:您State Updates May Be Asynchronous(即使用splice)应该只使用setState来更改状态。对于此问题,您可以将this.state.emails设置为等于slice的{​​{1}}。这是一个示例:

this.state.emails