5

My current state has this:

state = { items : [{id: 1, text: 'test words'}, {id: 2, text: 'another test'}]

Here's my function to remove objects from the array, trying to avoid mutating state.

handleRemove(passedInId) {

  const myItems = this.state.items

  const newArray = myItems.filter(item => item.id !== passedInId)

  this.setState(prevState => ({
    items: prevState.items = newArray
  }))

  console.log('handle remove runned', passedInId, myItems, newArray)

}

It works perfectly but would like to know if it's not anti-pattern before moving on with my life

Many THANKS!!

Clay_F
  • 561
  • 1
  • 6
  • 17
  • is there a reason for calling `prevState` and not just doing `this.setState(items: newArray)`? – A. L Mar 20 '17 at 02:47
  • Not sure, does this.setState(items:newArray) avoid state mutations? The docs show lots of prevState stuff – Clay_F Mar 22 '17 at 16:24

2 Answers2

11

Your function is almost right, and you have the right idea. You don't need to use the version of setState that takes a mutator function in your case, instead just do:

handleRemove(passedInId) {

  const myItems = this.state.items

  const newArray = myItems.filter(item => item.id !== passedInId)

  this.setState({
    items: newArray
  })

  console.log('handle remove runned', passedInId, myItems, newArray)

}

To be honest, this is simple enough that a one liner will do:

handleRemove(passedInId) {
  this.setState({items: this.state.items.filter(item => item.id !== passedInId)})
}
TomW
  • 3,923
  • 1
  • 23
  • 26
0

This is an anti-pattern. React handle state change and your object will not be mutated. This is what setState is for. I'm guessing that you don't want to update your state to avoid re-rendering your component. You can create a class variable and update it like you want without triggering a re-render. Something like this:

class MyComponent extends React.Component {
  constructor(props) {
    this.state = {};
    this.items = [{id: 1, text: 'test words'}, {id: 2, text: 'another test'}];
  }

  handleRemove(passedInId) {
    this.items = this.items.filter(item => item.id !== passedInId)
  }
}
Vincent D'amour
  • 3,746
  • 1
  • 27
  • 39
  • what do you mean by "React handle state change and your object will be mutated". Thanks for your help! – Clay_F Mar 22 '17 at 16:31
  • Well, you object won't be mutated, but a new object is created each time. So doing an equal operator will never return true since it's a new object. But doing setState will never mutate your object. – Vincent D'amour Mar 22 '17 at 20:05
  • 1
    I've never seen this pattern before. The pattern I typically see re: class variables is to use `this.someValue` in cases where you will need to attach a ref and almost nothing else. Mainly DOM-related references and never stateful stuff. Generally I use the pattern from the accepted answer, but in a Redux context. That `filter` method would be written in an action and then used as the return value in a reducer. – felguerez Mar 22 '17 at 20:11
  • 1
    You're totally right. I almost always use the pattern from the accepted answer too. But when reading the question, I thought the author wanted to filter the items without triggering any action or render. Also, base the question's code, you cannot tell if the filter is the app concern or the component concern, so you can't say the method will normally be handled by redux. – Vincent D'amour Mar 22 '17 at 20:29