Both works in that case, but you don't need to use that. Just setting the state will be okay:

this.setState({active: false})

But let me explain what if you have nested level of states like:

state = {
  foo: {
   a: 1,
   b: 2,
   c: 3
  }
}

And when you need to update the foo's c state only, then you'll need to merge the state like:

this.setState({ foo: {
  ...this.state.foo,
  c: 'updated value'
}})

So, the spread syntax merges object with later object. It's similar to Object.assign.

Answer from Bhojendra Rauniyar on Stack Overflow
🌐
Medium
medium.com › @thejasonfile › using-the-spread-operator-in-react-setstate-c8a14fc51be1
Using the spread operator in React setState | by Jason Arnold | Medium
May 25, 2017 - addNote(newNote) { this.setState({ toDoNotes: [...this.state.toDoNotes, newNote]}) } When the .addNote() function is called and passed a newNote object, the toDoNotes section of the state is updated so that it now includes the previous state as well as the addition of newNote. The spread operator is one of those tools that I tend to forget about because I don’t use it often enough.
Discussions

Using the spread operator in setState hook
Why bother even asking this? Try it out and see what happens. It will be much quicker? 🤷‍♂️ More on reddit.com
🌐 r/reactjs
5
0
October 6, 2019
reactjs - setState with spread operator - Stack Overflow
I was learning Forms in React and I came across the below code where a single setState method is used for multiple inputs to update the value provided by the user. Can anyone explain what spread op... More on stackoverflow.com
🌐 stackoverflow.com
How to use spread operator in setstate react class component
I am developing a component where I will get the data from a call back function. Initially the state of the component will be empty [], later once the callback function is called I need to update the More on stackoverflow.com
🌐 stackoverflow.com
Why use the spread operator when calling 'setState()' in React?
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 More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 3
4

Based upon the name setValues I assume you are referring to functional component state. (useState hook updates don't work quite the same as class-based component's setState lifecycle function)

Using the spread syntax allows for maintaining existing state, i.e. the new update [event.target.name]: event.target.value is merged into current state.

Given state { 'foo': 'bar' }

setValues(values => ({
   ...values, ['bizz']: 'buzz'
}))

New state { 'foo': 'bar', 'bizz': 'buzz' }

Without spreading in the previous state you are simply overwriting it with just an object {[event.target.name]: event.target.value}, so all previous state is lost.

Given state { 'foo': 'bar' }

setValues({
  ['bizz']: 'buzz'
})

New state { 'bizz': 'buzz' }

There are actually a couple things going on here. First is the spread syntax, the other is what is called a functional update. Functional updates allow the update to access the current state and make changes. This is a necessity when the next state depends on the previous state, like incrementing counters, and multiple state updates can be queued up during each render cycle.

setCount(count => count +1)

In the case of a form component where each property is an independent piece of state, then the following syntax is ok since each update to a field overwrites the current value:

setValues({
  ...values,
  [fieldName]: fieldValue
})
2 of 3
0

React may batch multiple setState() calls into a single update for performance.

Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.

For example, this code may fail to update the counter:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

To fix it, use a second form of setState() that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument:

// Correct
this.setState((state, props) => ({
  counter: state.counter + props.increment
}));

We used an arrow function above, but it also works with regular functions:

// Correct
this.setState(function(state, props) {
  return {
    counter: state.counter + props.increment
  };
});

Read more here on their official documentation

🌐
Rock Your Code
rockyourcode.com › react-set-state-with-prev-state-and-object-spread-operator
React setState() with prevState and Object Spread Operator | rockyourcode
September 30, 2021 - Instead you should use a function which takes the previous state as a first argument. // Correct this.setState((state, props) => ({ counter: state.counter + props.increment })); Let’s say you have an object in your state and want to use the ...
🌐
javascriptroom
javascriptroom.com › blog › spread-operator-in-react-setstate
Why Use the Spread Operator in React .setState()? (Even When the App Works Without It)
Use functional setState() for dependent updates: When the new state depends on the previous state (e.g., counters), use setState(prevState => ({ ...prevState, ...updates })). Beware of deep nesting: The spread operator is shallow—for deeply nested state (e.g., user.address.city), use nested spreads or libraries like Immer to simplify updates.
🌐
Medium
medium.com › @truongtronghai › spread-operator-ba867a0e97b4
Spread operator. Some ways to use it in React Js | by Truong Trong Hai | Medium
October 3, 2024 - When updating state in a functional component using the useState hook, the spread operator can help merge the new state with the existing state. const [state, setState] = useState({ name: "John", age: 30 }); const updateAge = () => { ...
🌐
Cloudhadoop
cloudhadoop.com › home
Three dots in react components with example|Spread operator
December 31, 2023 - It will only update the properties which are not changed. ... setEmployee is a function that updates the state of a component, It contains the code to update the state with initial values and new values.
Find elsewhere
🌐
DEV Community
dev.to › gamil91 › react-setstate-59l0
React setState() - DEV Community
September 14, 2021 - Clicking the button the first time will still console.log 0 but clicking it again the second time and the component re-renders, it will log 3. You can also use this if you’re updating an existing array or object in state by using the spread operator like so : state = { arr : [{obj1}, {obj2}, {obj3}] } handleClick = () => { this.setState(prevState => { return {array: [...prevState.arr, {newObj}]} }) } ... Uses the ... spread operator to make a copy of that arr ... The benefit of using a function instead of an object gives us access to the most updated state and will queue the setState() calls so that they run in order.
🌐
DhiWise
dhiwise.com › post › how-to-simplify-your-react-code-with-the-spread-operator
The Ultimate Guide To Using The React Spread Operator
October 31, 2023 - Mutating State Directly: One common mistake is to use the spread operator to mutate the state directly. In React, you should never mutate the state directly. Instead, you should always use setState (in class components) or the state update function returned by useState (in functional components) to update the state.
🌐
IQCode
iqcode.com › code › javascript › spread-operator-react
spread operator react Code Example
October 28, 2021 - spread operator example in reactjs ... spred oprator in react js react spread state into a function setstate spread operator array spread ract spreading an array in state react spreading an array in react class component use spread operator inside setstate when to use spread ...
🌐
Medium
iainrobertzon.medium.com › spread-operator-basics-and-react-97a555fe2eee
Spread Operator Basics and React. When working within React class… | by Iain Robertson | Medium
February 7, 2021 - The spread operator can also be used when passing an object into props in a react component. For instance, if we were in a situation where we were passing data into a functional component, ...
🌐
Stack Overflow
stackoverflow.com › questions › 60618020 › setstate-with-spread-operator
reactjs - setState with spread operator - Stack Overflow
setState in React should not mutate state. Instead with help of the spread operator a new object is being created containing the old values and the new [name] property.
🌐
Stack Overflow
stackoverflow.com › questions › 74446657 › how-to-use-spread-operator-in-setstate-react-class-component
How to use spread operator in setstate react class component
Mock: const items = { itemList: { itemOne: [{ id: "01", category: "It-A", isCreated:"true" }], itemDesc:[{ id:"01", type:"A-1", isCreated:"true" }] } ItemID:'123' } Code: class ItemComp extends React.Component{ this.state = { processingItems:[] onAddItemHandle = (processingItem) => { this.setState(prevState => ({ processingItems: [...prevState.processingItems, processingItem] })) } JEST: describe('handleonAddItem', () => { it('should allow to add multiple items based on prevState', () => { const compView = mountWithIntl( <compView itemId={12} /> } const instance = compView.find(compViewCompone
Top answer
1 of 4
4

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.

  • reactjs.org/docs/react-component.html#state

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:

  • doesitmutate.xyz

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.

2 of 4
3

Why use the spread operator at all?

The spread operator ... is often used for creating shallow copies of arrays or objects. This is especially useful when you aim to avoid mutating values, which is encouraged for different reasons. TLDR; Code with immutable values is much easier to reason about. Long answer here.

Why is the spread operator used so commonly in react?

In react, it is strongly recommended to avoid mutation of this.state and instead call this.setState(newState). Mutating state directly will not trigger a re-render, and may lead to poor UX, unexpected behavior, or even bugs. This is because it may cause the internal state to differ from the state that is being rendered.

To avoid manipulating values, it has become common practice to use the spread operator to create derivatives of objects (or arrays), without mutating the original:

// current state
let initialState = {
    user: "Bastian",
    activeTodo: "do nothing",
    todos: ["do nothing"]
}


function addNewTodo(newTodo) {
    // - first spread state, to copy over the current state and avoid mutation
    // - then set the fields you wish to modify
    this.setState({
        ...this.state,
        activeTodo: newTodo,
        todos: [...this.state.todos, newTodo]
    })
}

// updating state like this...
addNewTodo("go for a run")
// results in the initial state to be replaced by this:
let updatedState = {
    user: "Bastian",
    activeTodo: "go for a run",
    todos: ["do nothing", "go for a run"]
}

Why is the spread operator used in the example?

Probably to avoid accidental state mutation. While Array.filter() does not mutate the original array and is safe to use on react state, there are several other methods which do mutate the original array, and should not be used on state. For example: .push(), .pop(),.splice(). By spreading the array before calling an operation on it, you ensure that you are not mutating state. That being said, I believe the author made a typo and instead was going for this:

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

If you have a need to use one of the mutating functions, you can choose to use them with spread in the following manner, to avoid mutating state and potentially causing bugs in your application:

// here we mutate the copied array, before we set it as the new state
// note that we spread BEFORE using an array method
this.setState({
      todos: [...this.state.todos].push("new todo")
});

// in this case, you can also avoid mutation alltogether:
this.setState({
      todos: [...this.state.todos, "new todo"]
});
🌐
Stack Overflow
stackoverflow.com › questions › 68826619 › spread-operator-in-react-setstate-in-the-usestate-hook
reactjs - Spread operator in React .setState() in the useState Hook - Stack Overflow
Why is the spread operator used in setName() function how does it work. What this code does is it takes the input from the user and displays it on the screen but before using spread operator the
Top answer
1 of 1
2

You are likely being caught by React batching setState calls by shallow-merging the arguments you pass. This would result in only the last update being applied. You can fix this by only calling setState once, for example:

  componentDidMount () {

    const desc = window.localStorage.getItem('desc');
    const pic = window.localStorage.getItem('pic');
    const foo = window.localStorage.getItem('foo');

    this.setState({
        textArea: Object.assign({},
            desc ? { desc } : {},
            pic ? { pic } : {},
            foo ? { foo } : {}
        )
    });
  }
Run code snippetEdit code snippet Hide Results Copy to answer Expand

The other version is to pass an update function to setState rather than an update object, which is safe to use over multiple calls. The function is passed two arguments: the previous state, and the current props - whatever you return from the function will be set as the new state.

  componentDidMount () {

    const desc = window.localStorage.getItem('desc');
    const pic = window.localStorage.getItem('pic');
    const foo = window.localStorage.getItem('foo');

    this.setState(prevState => {
        if (desc) {
            return {
                textArea: {
                   ...prevState.textArea,
                   desc
                }
            }
        } else {
            return prevState;
        }
    });
    // Repeat for other properties
  }
Run code snippetEdit code snippet Hide Results Copy to answer Expand

It's a little more verbose using this approach, but does offer the opportunity to extract state updating functions outside of your component for testability:

  // Outside component
  const updateSubProperty = (propertyName, spec) => prevState => {
      return {
          [propertyName]: {
             ...prevState[propertyName],
             ...spec
          }
      }
  }

  const filterNullProperties = obj => {
      return Object.keys(obj).reduce((out, curr) => {
          return obj[curr] ? { ...out, [curr]: obj[curr] } : out;
      }, {});
  }

  componentDidMount () {
      this.setState(updateSubProperty("textArea",
          filterNullProperties(
              desc: window.localStorage.getItem('desc'),
              pic: window.localStorage.getItem('pic'),
              foo: window.localStorage.getItem('foo')
          )
      ));
  }
Run code snippetEdit code snippet Hide Results Copy to answer Expand

This way adds some complexity, but (in my opinion) gives a really readable component where it is clear to our future selves what we were trying to achieve.