Why use the spread operator when calling 'setState()' in React?

Terchilă Marian :

I just start picking up react.js so I went through a lot of tutorials and I've stumbled upon this bit which basically meant to delete an item from the state.

this is how the guy introduced to me the delete function

  delTodo = id => {
    this.setState({
      todos: [...this.state.todos.filter(todo => todo.id !== id)]
    });
  };

Since I am not so familiar with javascript I had a hard time figuring out what the ... operator is doing and why exactly is he using it in the given scenario. So in order to have a better understanding of how it works, I played a bit in the console and I've realised that array = [...array]. But is that true? Is this bit doing the same exact thing as the one from above?

  delTodo = id => {
    this.setState({
      todos: this.state.todos.filter(todo => todo.id !== id)
    });
  };

Could someone more experienced clarify to me why he has chosen to be using that approach instead of the one I've come up with?

goto1 :

As per the documentation:

Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.


So, in the example from the tutorial you've mentioned, you wouldn't need to make a copy of the array to update your state.

// GOOD
delTodo = id => {
  this.setState({
    todos: this.state.todos.filter(...)
  })
}

Array.filter method creates a new array and does not mutate the original array, therefore it won't directly mutate your state. Same thing applies to methods such as Array.map or Array.concat.

If your state is an array and you're applying methods that are mutable, you should copy your array.

See more to figure out which Array methods are mutable:

However, if you were to do something like the following:

// BAD
delTodo = id => {
  const todos = this.state.todos
  todos.splice(id, 1)
  this.setState({ todos: todos })
}

Then you'd be mutating your state directly, because Array.splice changes the content of an existing array, rather than returning a new array after deleting the specific item. Therefore, you should copy your array with the spread operator.

// GOOD
delTodo = id => {
  const todos = [...this.state.todos]
  todos.splice(id, 1)
  this.setState({ todos: todos })
}

Similarly with objects, you should apply the same technique.

// BAD
updateFoo = () => {
  const foo = this.state.foo // `foo` is an object {}
  foo.bar = "HelloWorld"
  this.setState({ foo: foo })
}

The above directly mutates your state, so you should make a copy and then update your state.

// GOOD
updateFoo = () => {
  const foo = {...this.state.foo} // `foo` is an object {}
  foo.bar = "HelloWorld"
  this.setState({ foo: foo })
}

Hope this helps.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=29637&siteId=1