filtering array to remove item react

4.2k Views Asked by At

I'm trying to use filter to remove an object from the array. When I click on the recently added item it will console.log the items id but doesn't remove the item from the array, not sure where I'm going wrong?

import React, { Component } from 'react'
import { reduxForm } from 'redux-form'
// import Input from '../forms/Input/Input'
import actions from './actions'
import { connect } from 'react-redux'
import styles from './Catalogue.styl'
 // import Checklist from './Checklist/Checklist'

@reduxForm({
  form: 'orderReview',
})
@connect(null, actions)

export default class Catalogue extends Component {
  constructor() {
    super()
    this.state = {
      filterText: '',
      favourites: [],
    data: [
    { id: 1, label: 'baguettes' },
    { id: 2, label: 'bread' },
    { id: 3, label: 'potatoes' },
    { id: 4, label: 'rice' },
    { id: 5, label: 'pasta' },
    { id: 6, label: 'chicken' },
    { id: 7, label: 'beans' },
    { id: 8, label: 'apples' },
    { id: 9, label: 'oranges' },
    { id: 10, label: 'grapes' },
    { id: 11, label: 'biscuits' },
  ],
}
}

handleFilterUpdate = event => {
  this.setState({
    filterText: event.target.value,
  })
}

addFavourite = (id) => {
  const favList = this.state.favourites.concat([id])
  this.setState({
    favourites: favList,
  })
  console.log(id)
 }

 removeFavourite = (id) => {
   console.log(id)
   const removeFav = this.state.favourites.filter((_, i) => i !== id)
     this.setState({
       favourites: removeFav,
     })
   }

  render() {
    const {
      data,
      filterText,
      favourites,
    } = this.state

   const NamesList = props => (
     <div>
     {props.data.filter(items => {
      return items.label.toLowerCase().indexOf(filterText.toLowerCase()) >= 0
    })
    .map(item => {
      return (
        <div
          key={item.id}
          onClick={() => props.addFavourite(item.id)}
        >
          {item.label}
        </div>
        )
      }
      )
    }

  </div>
)

const SaveName = props => {
  const idList = props.favourites.map(id => {
    const { label } = data[id]
    return (
      <div>
        <br />
        <li key={id} onClick={() => props.removeFavourite(data[id])}>{label}</li>
      </div>
    )
  })
  return (
    <div>{idList}</div>
  )
}

return (
  <div>
    <div className={styles.filtersList}>
      <ul className={styles.filtersUl}>
        <li className={styles.filtersLi}>znacky</li>
        <li className={styles.filtersLi}>zeme</li>
        <li className={styles.filtersLi}>Specialni</li>
      </ul>
    </div>

    <input
      type="text"
      value={filterText}
      onChange={this.handleFilterUpdate}
      placeholder="Hledat podle nazvu"
    />
    <NamesList data={data} addFavourite={this.addFavourite}/>
    {filterText}
    <SaveName favourites={favourites} removeFavourite={this.removeFavourite} />
  </div>
)
}
}
1

There are 1 best solutions below

4
Chris On BEST ANSWER

You are iterating through your entire array, and you compare the parameter id with the index of the currently processed item of the array.

Instead, compare the item.id with the parameter, not with i:

class MyApp extends React.Component {

  constructor() {
    super()
    this.state = {
      favourites: [
        { id: 1, label: 'baguettes' },
        { id: 2, label: 'bread' },
        { id: 3, label: 'potatoes' },
        { id: 4, label: 'rice' },
        { id: 5, label: 'pasta' },
        { id: 6, label: 'chicken' },
        { id: 7, label: 'beans' },
        { id: 8, label: 'apples' },
        { id: 9, label: 'oranges' },
        { id: 10, label: 'grapes' },
        { id: 11, label: 'biscuits' },
      ],
    }
  }

  removeFavourite = (id) => {
    const removeFav = this.state.favourites.slice();
    removeFav.splice(id, 1);
    this.setState({
      favourites: removeFav
    })
  }

  render() {
    return(
      <ul>
        {this.state.favourites.map((item, i) => <li key={item.id}>{item.label} <button onClick={this.removeFavourite.bind(this, i)}>Remove</button></li>)}
      </ul>
    );
  }
}

ReactDOM.render(<MyApp />, document.getElementById("myApp"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="myApp"></div>


Alternatively, you could also just use splice() to remove the item directly:

class MyApp extends React.Component {

  constructor() {
    super()
    this.state = {
      favourites: [
        { id: 1, label: 'baguettes' },
        { id: 2, label: 'bread' },
        { id: 3, label: 'potatoes' },
        { id: 4, label: 'rice' },
        { id: 5, label: 'pasta' },
        { id: 6, label: 'chicken' },
        { id: 7, label: 'beans' },
        { id: 8, label: 'apples' },
        { id: 9, label: 'oranges' },
        { id: 10, label: 'grapes' },
        { id: 11, label: 'biscuits' },
      ],
    }
  }

  removeFavourite = (id) => {
    const removeFav = this.state.favourites.filter(item => item.id-1 != id)
    this.setState({
      favourites: removeFav
    })
  }

  render() {
    return(
      <ul>
        {this.state.favourites.map((item, i) => <li key={item.id}>{item.label} <button onClick={this.removeFavourite.bind(this, i)}>Remove</button></li>)}
      </ul>
    );
  }
}

ReactDOM.render(<MyApp />, document.getElementById("myApp"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="myApp"></div>