You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何设置temp状态解决标签删除与编辑的冲突问题

解决方案:修复标签删除时输入框意外填充的问题

问题根源是事件冒泡:点击「X」按钮时,事件会向上传递到父级的<div className="tag-item">,触发绑定的handleItemEdit方法,导致标签值被填入输入框。你用temp状态尝试规避,但因为setState是异步操作,状态更新不会立即生效,加上事件执行顺序的问题,所以没达到效果。

直接通过阻止事件冒泡就能解决,同时可以移除多余的temp状态,简化代码:

修改后的完整代码

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends React.Component {
  state = {
    items: [],
    value: "",
    error: null
  };

  handleKeyDown = evt => {
    if (["Enter", "Tab", "|"].includes(evt.key)) {
      evt.preventDefault();

      var value = this.state.value.trim();

      if (value && this.isValid(value)) {
        this.setState({
          items: [...this.state.items, this.state.value],
          value: ""
        });
      }
    }
  };

  handleChange = evt => {
    this.setState({
      value: evt.target.value,
      error: null
    });
  };

  handleDelete = (item, evt) => {
    // 阻止事件冒泡到父元素,避免触发handleItemEdit
    evt.stopPropagation();
    this.setState({
      items: this.state.items.filter(i => i !== item)
    });
  };
  
  handleItemEdit = item =>{
    const result = this.state.items.filter(values=>values!==item)
    this.setState({
      value: item,
      error: null,
      items: result
    });
  }

  handlePaste = evt => {
    evt.preventDefault();

    var paste = evt.clipboardData.getData("text");
    var emails = paste.match(/[\w\d\.-]+@[\w\d\.-]+\.[\w\d\.-]+/g);

    if (emails) {
      var toBeAdded = emails.filter(email => !this.isInList(email));

      this.setState({
        items: [...this.state.items, ...toBeAdded]
      });
    }
  };

  isValid(email) {
    let error = null;

    if (this.isInList(email)) {
      error = `${email} has already been added.`;
    }

    if (!this.isEmail(email)) {
      error = `${email} is not a valid email address.`;
    }

    if (error) {
      this.setState({ error });

      return false;
    }

    return true;
  }

  isInList(email) {
    return this.state.items.includes(email);
  }

  isEmail(email) {
    return /[\w\d\.-]+@[\w\d\.-]+\.[\w\d\.-]+/.test(email);
  }

  render() {
    return (
      <>
        {this.state.items.map(item => (
          <div className="tag-item" key={item} onClick={() => this.handleItemEdit(item)}>
            {item}
            <button
              type="button"
              className="button"
              onClick={(evt) => this.handleDelete(item, evt)}
            >
              &times;
            </button>
          </div>
        ))}

        <input
          ref={this.state.items}
          className={"input " + (this.state.error && " has-error")}
          value={this.state.value}
          placeholder="Type or paste email addresses and press `Enter`..."
          onKeyDown={this.handleKeyDown}
          onChange={this.handleChange}
          onPaste={this.handlePaste}
        />

        {this.state.error && <p className="error">{this.state.error}</p>}
      </>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

关键修改点

  1. 移除了temp状态及相关判断逻辑,简化代码结构。
  2. 修改handleDelete方法,添加evt参数并调用evt.stopPropagation(),阻止事件冒泡到父级的handleItemEdit。
  3. 在按钮的onClick回调中传递evt对象给handleDelete。

这样点击「X」按钮时只会执行删除操作,不会触发输入框填充标签值的逻辑;点击标签本身时,依然会正常将标签值填入输入框并移除该标签。

内容的提问来源于stack exchange,提问作者user15361826

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:33:26