【问题标题】:How to delete an item from state array?如何从状态数组中删除项目?
【发布时间】:2016-07-19 12:08:49
【问题描述】:

故事是,我应该能够将 Bob、Sally 和 Jack 放入一个盒子中。我也可以从盒子中取出任何一个。移除后,不会留下任何插槽。

people = ["Bob", "Sally", "Jack"]

我现在需要删除“Bob”。新数组将是:

["Sally", "Jack"]

这是我的反应组件:

...

getInitialState: function() {
  return{
    people: [],
  }
},

selectPeople(e){
  this.setState({people: this.state.people.concat([e.target.value])})
},

removePeople(e){
  var array = this.state.people;
  var index = array.indexOf(e.target.value); // Let's say it's Bob.
  delete array[index];
},

...

在这里,我向您展示了一个最少的代码,因为它还有更多内容(onClick 等)。关键部分是从数组中删除、移除、销毁“Bob”,但removePeople() 在调用时不起作用。有任何想法吗?我是looking at this,但我可能做错了,因为我使用的是 React。

【问题讨论】:

    标签: javascript arrays reactjs


    【解决方案1】:

    当使用 React 时,你不应该直接改变状态。如果一个对象(或者Array,它也是一个对象)被改变了,你应该创建一个新的副本。

    其他人建议使用Array.prototype.splice(),但该方法会改变数组,因此最好不要将splice() 与React 一起使用。

    最简单的使用Array.prototype.filter()创建一个新数组:

    removePeople(e) {
        this.setState({people: this.state.people.filter(function(person) { 
            return person !== e.target.value 
        })});
    }
    

    【讨论】:

    • 是的,这是声明方式。使用 prevState 和箭头函数的替代方法:this.setState(prevState => ({ people: prevState.people.filter(person => person !== e.target.value) }));
    • 这应该是 React 惯用语从不改变状态的公认答案。
    • 或使用索引:this.state.people.filter((_, i) => i !== index)
    • 有不可变的切片和可变的拼接
    • 这个答案的问题是,如果您有几个同名的人,您将删除所有这些人。在您可能有欺骗的情况下使用索引更安全
    【解决方案2】:

    要从数组中删除一个元素,只需:

    array.splice(index, 1);
    

    在你的情况下:

    removePeople(e) {
      var array = [...this.state.people]; // make a separate copy of the array
      var index = array.indexOf(e.target.value)
      if (index !== -1) {
        array.splice(index, 1);
        this.setState({people: array});
      }
    },
    

    【讨论】:

    • 在我的情况下是:array.splice(array, 1); 谢谢
    • 使用 React 时,通常应该避免直接改变你的状态。您应该创建一个新数组并使用setState()
    • 在这种情况下,我建议使用 Array.from(this.state.items) 而不是扩展运算符。这是因为 Array.from 专门用于此用途。
    • 小建议,在拼接数组之前添加对“index !== -1”的检查,防止不必要的移除。
    • 这是反模式。拼接函数变异或改变相同
    【解决方案3】:

    这是 Aleksandr Petrov 使用 ES6 的响应的一个细微变化

    removePeople(e) {
        let filteredArray = this.state.people.filter(item => item !== e.target.value)
        this.setState({people: filteredArray});
    }
    

    【讨论】:

      【解决方案4】:

      使用.splice 从数组中删除项目。使用delete,数组的索引不会改变,但特定索引的值为undefined

      splice() 方法通过删除现有元素和/或添加新元素来更改数组的内容。

      语法: array.splice(start, deleteCount[, item1[, item2[, ...]]])

      var people = ["Bob", "Sally", "Jack"]
      var toRemove = 'Bob';
      var index = people.indexOf(toRemove);
      if (index > -1) { //Make sure item is present in the array, without if condition, -n indexes will be considered from the end of the array.
        people.splice(index, 1);
      }
      console.log(people);

      编辑:

      正如justin-grant 所指出的,根据经验,永远不要直接对this.state 进行变异,因为之后调用setState() 可能会替换您所做的变异。将 this.state 视为不可变的。

      另一种方法是,在this.state 中创建对象的副本并操作这些副本,然后使用setState() 将它们分配回去。可以使用Array#mapArray#filter等。

      this.setState({people: this.state.people.filter(item => item !== e.target.value);});
      

      【讨论】:

      • 确保不要使用 splice 或任何直接更改状态变量的方法。相反,您需要制作数组的副本,从副本中删除项目,然后将副本传递给setState。其他答案包含有关如何执行此操作的详细信息。
      【解决方案5】:

      从反应状态数组中删除项目的简单方法:

      当任何数据从数据库中删除并更新列表而不调用 API 时,您将已删除的 id 传递给此函数,此函数从列表中删除已删除记录

      export default class PostList extends Component {
        this.state = {
            postList: [
              {
                id: 1,
                name: 'All Items',
              }, {
                id: 2,
                name: 'In Stock Items',
              }
            ],
          }
      
      
          remove_post_on_list = (deletePostId) => {
              this.setState({
                postList: this.state.postList.filter(item => item.post_id != deletePostId)
              })
            }
        
      }

      【讨论】:

      • 你能解释一下这与这个三年前的问题的其他 8 个答案有何不同吗? From review
      • 在上面的代码中它将重新创建新的数据数组但跳过“deletePostId”这个id
      • 使用item.post_id !== deletePostId
      【解决方案6】:

      filter 方法是在不接触状态的情况下修改数组的最佳方法。

      它根据条件返回一个新数组。

      在您的情况下,过滤器检查条件person.id !== id 并根据条件创建一个不包括项目的新数组。

      const [people, setPeople] = useState(data);
      
      const handleRemove = (id) => {
         const newPeople = people.filter((person) => person.id !== id);
      
         setPeople( newPeople);
       };
      
      <button onClick={() => handleRemove(id)}>Remove</button>
      

      不建议: 但是,如果您没有任何 id,您也可以使用项目索引作为条件。

      index !== itemIndex

      【讨论】:

        【解决方案7】:

        使用“拼接”提到的一些答案,正如 Chance Smith 所说的那样,改变了数组。我建议你使用方法调用'slice' (Document for 'slice' is here) 复制原始数组。

        【讨论】:

        • 你能提供一个最小的例子来说明你在这里讨论的内容吗?谢谢。
        【解决方案8】:

        使用slice 的简单解决方案不改变状态

        const [items, setItems] = useState(data);
        const removeItem = (index) => {
          setItems([
                     ...items.slice(0, index),
                     ...items.slice(index + 1)
                   ]);
        }
        

        【讨论】:

          【解决方案9】:

          非常简单 首先你定义一个值

          state = {
            checked_Array: []
          }
          

          现在,

          fun(index) {
            var checked = this.state.checked_Array;
            var values = checked.indexOf(index)
            checked.splice(values, 1);
            this.setState({checked_Array: checked});
            console.log(this.state.checked_Array)
          }
          

          【讨论】:

          • 请不要这样做。它直接改变状态。 splice 就位。
          【解决方案10】:
          removePeople(e){
              var array = this.state.people;
              var index = array.indexOf(e.target.value); // Let's say it's Bob.
              array.splice(index,1);
          }
          

          Redfer doc 了解更多信息

          【讨论】:

          • 这会直接改变状态。不要这样做 - 始终将状态视为不可变的。
          【解决方案11】:
          const [people, setPeople] = useState(data);
          
          const handleRemove = (id) => {
             const newPeople = people.filter((person) => { person.id !== id;
               setPeople( newPeople );
               
             });
           };
          
          <button onClick={() => handleRemove(id)}>Remove</button>
          

          【讨论】:

          • 您的代码不完整,请检查并更正。还要确保解释代码,而不是仅仅提供代码。
          【解决方案12】:

          您忘记使用setState。示例:

          removePeople(e){
            var array = this.state.people;
            var index = array.indexOf(e.target.value); // Let's say it's Bob.
            delete array[index];
            this.setState({
              people: array
            })
          },
          

          但最好使用filter,因为它不会改变数组。 示例:

          removePeople(e){
            var array = this.state.people.filter(function(item) {
              return item !== e.target.value
            });
            this.setState({
              people: array
            })
          },
          

          【讨论】:

          • “但最好使用filter,因为它不会改变数组”——为什么还要显示顶级版本,因为它令人困惑、不正确和有问题?我了解您正在尝试使用 OP 的示例,但状态上的delete 从根本上被破坏了,即使使用setState
          【解决方案13】:

          这里几乎所有的答案似乎都是针对类组件的,这是一个在功能组件中对我有用的代码。

          const [arr,setArr]=useState([]);
          const removeElement=(id)=>{
              var index = arr.indexOf(id)
              if(index!==-1){
                setArr(oldArray=>oldArray.splice(index, 1));
              }
          }
          

          【讨论】:

          • splice 不返回新数组。它就位。
          【解决方案14】:
          const [randomNumbers, setRandomNumbers] = useState([111,432,321]);
          const numberToBeDeleted = 432;
          
          // Filter (preferred)
          let newRandomNumbers = randomNumbers.filter(number => number !== numberToBeDeleted)
          setRandomNumbers(newRandomNumbers);
          
          //Splice (alternative)
          let indexOfNumberToBeDeleted = randomNumbers.indexOf(numberToBeDeleted);
          let newRandomNumbers = Array.from(randomNumbers);
          newRandomNumbers.splice(indexOfNumberToBeDeleted, 1);
          setRandomNumbers(newRandomNumbers);
          
          
          //Slice (not preferred - code complexity)
          let indexOfNumberToBeDeleted = randomNumbers.indexOf(numberToBeDeleted);
          let deletedNumber = randomNumbers.slice(indexOfNumberToBeDeleted, indexOfNumberToBeDeleted+1);
          let newRandomNumbers = [];
          for(let number of randomNumbers) {
              if(deletedNumber[0] !== number)
                  newRandomNumbers.push(number);
          };
          setRandomNumbers(newRandomNumbers);
          

          【讨论】:

            【解决方案15】:
            const array = [...this.state.people];
            array.splice(i, 1);
            this.setState({people: array});         
            

            【讨论】:

              猜你喜欢
              • 2022-12-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-03-10
              相关资源
              最近更新 更多