You still don't want to mutate state. So if your state is an object, you'll want to create a new object and set with that. This may involve spreading the old state. For example:

const [person, setPerson] = useState({ name: 'alice', age: 30 });

const onClick = () => {
  // Do this:
  setPerson(prevPerson => {
    return { 
      ...prevPerson, 
      age: prevPerson.age + 1 
    }
  })
  // Not this:
  //setPerson(prevPerson => {
  //  prevPerson.age++;
  //  return prevPerson;
  //});
}

That said, using hooks you often no longer need your state to be an object, and can instead use useState multiple times. If you're not using objects or arrays, then copying is not needed, so spreading is also not needed.

const [name, setName] = useState('alice');
const [age, setAge] = useState(30);

const onClick = () => {
  setAge(prevAge => prevAge + 1);
}
Answer from Nicholas Tower on Stack Overflow
🌐
W3Schools
w3schools.com › react › react_es6_spread.asp
React ES6 Spread Operator
React Compiler React Quiz React Exercises React Syllabus React Study Plan React Server React Interview Prep React Bootcamp ... The JavaScript spread operator (...) copies all or part of an existing array or object into another array or object.
Discussions

What is the reason I have to use spread operator in React hooks?
Expected behavior To rendered counter increase by one on each click Actual behavior Rendered counter doesn't increase, but internal does (as seen by alert messages). And look at this screenshot: ht... More on stackoverflow.com
🌐 stackoverflow.com
September 18, 2020
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 More on stackoverflow.com
🌐 stackoverflow.com
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
Need help with useState hook - can't update an array using the spread operator
Both versions look like they should work -- maybe it's something in the surrounding context? Can you share more and/or repro in a codepen? More on reddit.com
🌐 r/reactjs
9
2
December 5, 2021
🌐
Stack Overflow
stackoverflow.com › questions › 63963826 › what-is-the-reason-i-have-to-use-spread-operator-in-react-hooks
What is the reason I have to use spread operator in React hooks?
September 18, 2020 - When you const newAll = all you are saving the reference to the state all to newAll as well, but you const newAll = [...all] you are first spreading the state into a new array reference then saving it to newAll ... const all = [1,2,3]; const newAll1 = all; const newAll2 = [...all]; console.log(newAll1 === all); // true console.log(newAll2 === all); // false ... Even though you shallowly copied all, newAll[0].votes++ would still be considered a state mutation. If you need to update an element of an array in react state then you should also shallowly copy the properties of any object you intend to update.
🌐
DEV Community
dev.to › jamenamcinteer › all-the-hooks-series-usestate-3faf
All the Hooks Series: useState - DEV Community
June 5, 2020 - There are a couple of ways you can update a state value that is an object and ensure that React recognizes the change and re-renders the component. One is to use Object.assign to create a new object and set the state to use this value. The other is to use the ES6 spread operator to create a new object with the values of the old object and any changes.
🌐
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
... Sign up to request clarification or add additional context in comments. ... Save this answer. ... Show activity on this post. Spread syntax can be used when all elements from an object or array need to be included in a list of some kind.
Find elsewhere
🌐
JavaScript in Plain English
javascript.plainenglish.io › forms-in-react-with-hooks-809a3f38ed4
Forms in React with Hooks. How to use spread operator and hooks to… | by Saranjeet Singh | JavaScript in Plain English
May 26, 2022 - We can use the push() method but that will alter the arr1 array. What we can do here is create a second array, arr2 and store all the elements in it and add 5 at the end. We can do that using the spread operator in JavaScript. This part will show how to use hooks to use forms in React.
🌐
Scribd
scribd.com › document › 822378308 › rEact-hooks
Using the Spread Operator in React | PDF | Programming Paradigms | Computing
The spread operator in JavaScript allows for copying or expanding elements of arrays and objects, and is particularly useful in React for handling props, state, and data manipulation.
🌐
Medium
medium.com › @fa20-bse-059 › understanding-the-spread-operator-in-react-native-21be8f660d65
Understanding the Spread Operator in React Native | by saad | Medium
January 7, 2025 - State management is one of the most common areas where the spread operator shines. When updating state, especially with React hooks like useState, you often need to update an object or array without mutating the original state.
🌐
Michaelcharl
michaelcharl.es › aubrey › en › code › dot-dot-dot-javascript-and-react-spread-operator
Three Dots: The Spread Operator in JavaScript and React | MichaelCharl.es/Aubrey (Michael Charles Aubrey)
May 19, 2023 - We're using the useState hook to set the initial user state and defining a handleAgeChange function. This function uses the spread operator to copy the properties of the user object into a new object (newUser). Then, we update the age in newUser to the new age (newAge) and set this new user object as the state using setUser. Using the spread operator here is important for maintaining state immutability. By creating a new object before updating the state, React can efficiently track state changes.
🌐
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 - Some ways to use it in React Js · You can use the spread operator to pass all properties of an object as props to a component. const cardProps = { title: "Hello World", description: "This is a description."
🌐
GeeksforGeeks
geeksforgeeks.org › reactjs › what-is-the-meaning-of-spread-operator-in-reactjs
What is the Meaning of Spread Operator (...) in Reactjs? - GeeksforGeeks
July 23, 2025 - React Hooks · React Router · React Advanced · React Examples · React Interview Questions · React Projects · Last Updated : 23 Jul, 2025 · The Spread Operator ( ... ) in react is used to manage and manipulate props, arrays, and states.
🌐
CoderCrafter
codercrafter.in › home › blog › master the react es6 spread operator: a complete guide with examples & best practices
Master the React ES6 Spread Operator: A Complete Guide with Examples & Best Practices | CoderCrafter
October 10, 2025 - The spread operator is the perfect tool for this job. It allows us to create new arrays and objects based on existing ones, without ever modifying the originals. This is especially critical when working with state in useState and useReducer hooks...
🌐
CoreUI
coreui.io › blog › draft-how-to-replace-all-occurrences-of-a-string-in-javascript
Mastering the Spread Operator (<code>...</code>) in React.js · CoreUI
September 3, 2023 - This method is particularly effective ... React state, the spread operator simplifies the process of creating a new array that includes updates or additions without mutating the existing array....
🌐
Reddit
reddit.com › r/reactjs › need help with usestate hook - can't update an array using the spread operator
r/reactjs on Reddit: Need help with useState hook - can't update an array using the spread operator
December 5, 2021 -

I am fairly new to React and I think I am missing an important concept about state.

I am trying to update a state variable, specifically an array. The following function successfully updates the array if I use Array.push(), but not if I use destructuring/the spread operator. What am I missing? Also, the template is completely non-reactive - even when the console.log statement displays the correct value, the HTML does not.

function MyComponent() {
    const [selection, setSelection] = useState([]);

    const handleSelection = (id) => {
        // doesn't work
        // let newSelection = [...selection, id];

        let newSelection = selection;
        newSelection.push(id);

        // Prints the correct value when using Array.push() but not destructuring
        console.log(selection);

        setSelection(newSelection);
    };

    return (
        {/* never changes */}
        <pre>{JSON.stringify(selection, null, 2)}</pre>
    )
}

EDIT: I thought this was a problem with how I was setting state on the selection variable, but it turns out the issue was with other parts of my code that are tangentially related to this. The problem was that I was trying to to loop over some data and generate a component for each datum, but I wasn't doing that correctly. I was setting a different state variable to hold these components, and the various pieces of state were out of sync. Here is a repro of the working code, where I am mapping the components correctly (in the template directly rather than setting state, which seems to be better practice). As you can see, spread/destructuring works perfectly as expected now.

Top answer
1 of 2
5

Reason is how you're accessing previous value to add new element:

for (let i = 0; i < data.breakouts.length; i++) {
  data.breakouts[i].start = new Date(data.breakouts[i].start);
  setFields({
    ...fields,
    [data.breakouts[i].name]: data.breakouts[i].start
  })
}

since fields will be updated only on next render, you are adding single element(but each loop it's different element) to the array.

The same would be without hooks/react:

const start = [];
for(let i = 0; i< 5; i++) console.log([...start, i]);

This will never output [0,1,2,3,4].

What can you do.

Option 1. Collect data in interm variable:

const temp = {};
for (let i = 0; i < data.breakouts.length; i++) {
  data.breakouts[i].start = new Date(data.breakouts[i].start);
  data.breakouts[i].end = new Date(data.breakouts[i].end);
  temp[data.breakouts[i].name] = data.breakouts[i].start
}
setFields({
  ...fields,
  ...temp
});

Option 2. Use functional version of setter as an accumulator:

for (let i = 0; i < data.breakouts.length; i++) {
  data.breakouts[i].start = new Date(data.breakouts[i].start);
  setFields(({fields: prevFields}) => ({
    ...prevFields,
    [data.breakouts[i].name]: data.breakouts[i].start
  }))
}

I'd prefer first option for 2 reasons:

  1. it would be better finally move data transform closer to call point, so instead of axios.get there would be some API.getMeaningfullThings returning structure you need; so it's easier to refactor
  2. maybe slighter more code shows better what's going on(it's just a transforming, not a filtering or any React-specific thing)
2 of 2
3

If I understand correctly, you have problem with setState from first example. Te reason is that you are calling setState inside of a loop, and you are trying to spread the old state, but the state doesn't get set before your loop is done, so you have to accumulate everything you want to put into your state inside the loop and set it at the end.

🌐
LogRocket
blog.logrocket.com › home › using react usestate with an object
Using React useState with an object - LogRocket Blog
June 4, 2024 - The spread operator helps avoid such problems by providing a clean and safe way to perform state updates · Let’s explore how to update an array of objects in the React state.