【问题标题】:Improper removal of tags based on their keys in React js根据 React js 中的键不正确地删除标签
【发布时间】:2019-12-27 07:47:39
【问题描述】:

我有一个输入文本框。 enter 上的值将填充为下面的标签。根据索引删除标签时,不会按预期删除。关闭单个标签时会删除多个标签。

链接 [codesandbox]:https://codesandbox.io/s/tender-chebyshev-iek41

class App extends React.Component{
  state={
    text:[],
    tags:[]
  };
  handleSearch = (value) => {
    const tagsMap = [...this.state.tags];
    tagsMap.push(`${value}`.trim());
    this.setState({text:value,tags:tagsMap},()=>console.log(this.state.text))
  }
  onCloseTag = (key) => {
    console.log('Closed', key);
    this.setState({
      tags: this.state.tags.filter((_, index) => index !== key)
    });

  }
  render(){
    const { tags } = this.state;
    return (
      <div className="App">

        <h2>Start editing to see some magic happen!</h2>
        <Search
        placeholder="input search text"
        onSearch={(value)=>this.handleSearch(value)}
        style={{ width: 200 }}
      /><br/>
      {tags.map((tag,i) => <Tag key={i} closable onClose={() => this.onCloseTag(i)} color="#f50">{tag}</Tag> )}
      </div>
    );
  }
}

预期:在关闭该特定标签时删除一个标签

实际:关闭时删除多个标签

【问题讨论】:

  • 切勿将索引用于此类操作。而是创建对象的 Id 并使用它来删除项目

标签: reactjs input tags antd


【解决方案1】:

在ReactJS中使用索引为key是anti-pattern

修改你的代码你就能明白为什么会这样:

      {JSON.stringify(tags)}//add this line
      {tags.map((tag,i) => <Tag key={i} closable onClose={() => this.onCloseTag(i)} color="#f50">{tag}</Tag> )}

【讨论】:

    【解决方案2】:

    切勿将索引用于此类操作。而是创建对象的 Id 并使用它来删除项目。已将您的标签数组更改为包含每个标签的唯一 ID 的对象数组。

       handleSearch = (value) => {
          //Add Id to be used for removal later
         const tagsMap = [...this.state.tags,{Id:Math.random(),value}];
          this.setState({text:value,tags:tagsMap},()=>console.log(this.state.text)) 
              }
    

    首先传递 Id 而不是键,并重构代码以使用对象数组而不是字符串数组

     {tags.map((tag,i) => <Tag key={i} closable onClose={() => this.onCloseTag(tag.Id)} color="#f50">{tag.value}</Tag> )}
    

    然后使用该 ID 删除

      onCloseTag = (Id) => {
        console.log('Closed', key);
        this.setState({
          tags: this.state.tags.filter(Tag => Tag.Id!== Id)
        });
    
      }
    

    【讨论】:

      【解决方案3】:

      e.preventDefault() 完成了这项工作。只需将e(事件)传递给onCloseTag 函数即可。

      {tags.map((tag,i) => <Tag key={i} closable onClose={(e) => this.onCloseTag(e,i)} color="#f50">{tag}</Tag> )}
      

      onCloseTag函数应该是,

      onCloseTag = (e,key) => {
        e.preventDefault();   //This did the job.
        console.log('Closed', key);
        this.setState({
            tags: this.state.tags.filter((_, index) => index !== key)
        });
      }
      

      Demo

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-08
        • 1970-01-01
        • 1970-01-01
        • 2019-09-22
        • 1970-01-01
        • 2021-03-13
        • 1970-01-01
        相关资源
        最近更新 更多