javascript - 使用 this.setState 后 react 不呈现正确的状态值

标签 javascript reactjs

我正在尝试构建一个组件,自动检查输入字段中的有效电子邮件地址,然后使用 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.emailsslice。这是一个例子:

this.setState({ emails: this.state.emails.slice(0, -1) });

关于javascript - 使用 this.setState 后 react 不呈现正确的状态值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51953950/

相关文章:

javascript - 将 useEffect 与事件监听器结合使用

javascript - html中的工具提示

javascript - 正则表达式:从没有文件扩展名的 URL 捕获文件名

javascript - 在 React 中使用 setState 进行多个获取请求

javascript - 在 React 中操作 DOM

javascript - 单击子元素会给 onclick 事件reactjs 带来未定义

javascript - 无法使用它的属性获取 xml 元素的内部 HTML

javascript - 动态添加选项到脚本

javascript - 是否可以阻止图像错误出现到控制台?

javascript - 多个文本字段 onChange 函数问题