简体   繁体   中英

Removing an array item with splice if the value(s) is(are) true

I am trying to remove checked items that are true from an array with the array.splice method. It seems to work most of the time, but for some reason, there are times when two or three items are checked, and only one item is removed from the checked list when I run the function that splices the array items.

I've tried mapping through the array and returning the new array with the spliced items removed, kind of works but not always. I'm mapping the array with two arguments, (index and item). I am creating an if statement that if the item is checked, or done, to remove it by (index, 1). After that I'm returning the new array. The issue is happening in the removeCheckedBeer function

  // if there is no item string, create an empty array
  const items = JSON.parse(localStorage.getItem('items')) || []

  function addItem(e) {
    // prevent the form from submitting
    e.preventDefault()
    const text = (this.querySelector('[name=item]')).value
    const item = {
      text,
      done: false
    }
    items.push(item)
    // rerenders list without having to reload the page
    populateList(items, itemsList)
    localStorage.setItem('items', JSON.stringify(items))
    this.reset()
  }

  // function removes all items in the array
  const removeAllItems = e => {
    e.preventDefault()
    items.splice(0)
    localStorage.setItem('items', JSON.stringify(items))
    populateList([], itemsList)
  }

  // remove all checked items
  const removeCheckedBeer = e => {
    e.preventDefault()
    items.map((item, index) => {
      if (item.done === true) {
        console.log(index, item)
        items.splice(index, 1)
      }
      return items
    })
    localStorage.setItem('items', JSON.stringify(items))
    populateList(items, itemsList)
  }

  // toggle a single item
  const toggleDone = e => {
    if (!e.target.matches('input')) return // skip this unless it's an input
    const el = e.target
    const index = el.dataset.index
    // toggle from done to !done
    items[index].done = !items[index].done
    localStorage.setItem('items', JSON.stringify(items))
  }

  // toggle inventory of all items to true or false
  const toggleAllItems = e => {
    items.forEach((item, index, array) => {
      e.target.name === 'checkAll' ? (items[index].done = true) : (items[index].done = false)
  console.log(e.target.name)
})
localStorage.setItem('items', JSON.stringify(items))
populateList(items, itemsList)
  }

  const populateList = (beers = [], beerList) => {
    // map through the array, and create a new array to render the beer list
    beerList.innerHTML = beers.map((beer, i) => {
      return `
        <li>
          <input type="checkbox" data-index=${i} id="item${i}" 
${beer.done ? 'checked' : ''} />
          <label for="item${i}">${beer.text}</label>
        </li>
      `
    }).join('')
  }

So I'm expecting that the number of checked items will be removed from the array starting at the index of the first checked item. The result is that the item is being removed, but at times, just one item at a time. Sometimes more than one item is being removed. Can someone explain what's happening with my function?

The issue with splice() is that the element is removed from the array shifts all other elements down by one as well. It would be better to use filter() :

items = items.filter(e => e.done !== true);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM