2

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>
)
}
}
4
  • You are not returning anything in your filter-callback. Therefore your removeFav is empty. Use .filter((_, i) => {return i !== id;}) Commented Jun 29, 2017 at 14:39
  • You should not be directly modifying your state as you are addFavourite with concat. Instead try using the this.setState((prev, props) => ({ })) definition to modify using the previous state Commented Jun 29, 2017 at 14:40
  • @Bjoern thats not correct, with simple expressions, like i !== id, the return is implicit without curly braces Commented Jun 29, 2017 at 14:40
  • @m_callens So I learned something too. Thanks! Commented Jun 30, 2017 at 5:20

1 Answer 1

2

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>

Sign up to request clarification or add additional context in comments.

4 Comments

Shouldn't removeFavourite be more like: removeFavourite = id => this.setState(prevState => ({ favourites: prevState.favourites.filter(item => item.id !== id) })) ?
@PeterLaCombJr. hmm what's the difference?
Thanks for providing the example,looks like it will work although I'm having trouble implementing it, but I need to refactor the code anyway for immutability
@chris - This example is trivial, but in a more complicated app, you have to deal with asynchrony in state updates: facebook.github.io/react/docs/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.