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)} > × </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);
关键修改点
- 移除了
temp状态及相关判断逻辑,简化代码结构。 - 修改
handleDelete方法,添加evt参数并调用evt.stopPropagation(),阻止事件冒泡到父级的handleItemEdit。 - 在按钮的
onClick回调中传递evt对象给handleDelete。
这样点击「X」按钮时只会执行删除操作,不会触发输入框填充标签值的逻辑;点击标签本身时,依然会正常将标签值填入输入框并移除该标签。
内容的提问来源于stack exchange,提问作者user15361826
相关产品推荐
相关产品推荐

